Home > Software design >  How to give data to ManyToManyField from view in django
How to give data to ManyToManyField from view in django

Time:01-20

Hello i am new to django and i am trying to create a page where we can add and participate in various events.

This is the model i created for my database

model.py

class Venue(models.Model):
    name = models.CharField('Venue Name', max_length=120)
    address = models.CharField(max_length=300)
    zip_code = models.CharField('Zip Code', max_length=6)
    phone = models.CharField('Contact Number', max_length=25, blank=True)
    web = models.URLField('Website Address', blank=True)
    email = models.EmailField('Email', blank=True)
    owner = models.IntegerField('Venue Owner', blank=False, default=1)
    venue_image = models.ImageField(null=True, blank=True, upload_to="images/")

class Event(models.Model):
    name = models.CharField('Event Name', max_length=120)
    event_date = models.DateTimeField('Event Date')
    venue = models.ForeignKey(Venue, blank=True,null=True, on_delete=models.CASCADE)
    manager = models.ForeignKey(User,blank=True,null=True,on_delete=models.SET_NULL)
    description = models.TextField(blank=True, )
    attendees = models.ManyToManyField(User,blank=True, related_name='attendees')

here i am trying to make a link by clicking that link user participate to that Event but i am not getting how to put the user data in the above attendees field

view function

def attendees(request):
    Event.attendees.add(request.user)
    return redirect('list-events')

error : AttributeError at /participate/ 'ManyToManyDescriptor' object has no attribute 'add'

link

<a href="{% url 'participate' %}">Participate</a>

url.py

path('participate/', attendees, name='participate')  

CodePudding user response:

You need to specify for which event the user will be added, so the view should look like:

from django.contrib.auth.decorators import login_required
from django.shortcuts import get_object_or_404, redirect
from django.views.decorators.http import require_POST

@require_POST
@login_required
def attendees(request, pk):
    event = get_object_or_404(Event, pk=pk)
    event.attendees.add(request.user)
    return redirect('list-events')

participating should be done through a POST request since it alters entities. A GET request should only be used to retrieve data, not update it.

and the urls.py thus should contain a URL parameter for the primary key:

path('participate/<int:pk>/', attendees, name='participate')

Finally the template should thus make a POST request to the path with the primary key of the event:

<form method="post" action="{% url 'participate' pk=event.pk %}">
    <button type="submit">Participate</button>
<form>

Note: You can limit views to a view to authenticated users with the @login_required decorator [Django-doc].


Note: One can use the @require_POST decorator [Django-doc] to restrict the view to only be accessible for a POST request.


Note: It is normally better to make use of the settings.AUTH_USER_MODEL [Django-doc] to refer to the user model, than to use the User model [Django-doc] directly. For more information you can see the referencing the User model section of the documentation.

CodePudding user response:

Here is the easiest way of doing it. As I can understand Venue model is saved by the admin(i.e you). If not then you have to save the Venue first.

Now the key point is, in relationship fields, you have to pass the whole inheriting model object.

You can do something like this:

#in login view

def login(request):
   #your code
   request.session['userID']=userID
   #your code

now you can use the session variable (i.e userID) in any view or template

#participate view

from mymodels import Event,Venue

def participate(request):
     #your GET or POST parameters here
     user=user_model.objects.get(id=request.session['userID'])
     venue=Venue.objects.get(id=venue_id) #OR filter it by any other field like name
     E1=Event()
     E1.attendees= user
     E1.venue= venue
     E1.manager= user
     E1.name= name_from_request_parameters
     E1.description= description_from_request_parameters
     E1.event_date= event_date_from_request_parameters
     E1.save()

Tip: use default current date in datefield like event_date = models.DateTimeField(default=datetime.now())

  •  Tags:  
  • Related