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
Participate
url.py
path('participate/', attendees, name='participate')
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.
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())
Related
In the following mode in my project, I want to assign the author variable of class upon the creation of model, on user end this could be done via request.user but as the class can be only instantiated from the admin area, this doesn't work.
class Blog(models.Model):
title = models.CharField(max_length=300)
content = RichTextField()
author = models.ForeignKey(User, related_name="Author", auto_created= True, on_delete=
models.CASCADE)
date = models.DateTimeField(auto_now_add= True)
The auto_created=… field [Django-doc] is about model inheritance, it does not add the logged in user: the model layer is request unaware, and there is not per se a "logged in user". You thus remodel this to:
from django.conf import settings
from django.db import models
class Blog(models.Model):
title = models.CharField(max_length=300)
content = RichTextField()
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
related_name='blogs',
on_delete=models.CASCADE,
editable=False,
)
date = models.DateTimeField(auto_now_add=True)
In the model admin for the Blog model, you can work with:
from django.contrib import admin
#admin.register(Blog)
class BlogAdmin(admin.ModelAdmin):
# …
def save_model(self, request, obj, form, change):
obj.author = request.user
return super().save_model(request, obj, form, change)
Note: The related_name=… parameter [Django-doc]
is the name of the relation in reverse, so from the Blog model to the User
model in this case. Therefore it (often) makes not much sense to name it the
same as the forward relation. You thus might want to consider renaming the Author relation to blogs.
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.
I'm trying to link a "normal" model field with an admin model field, for example I have a table "Post" and I want to add the admin username as a ForeignKey to the field "Author" of the table Post.
I mean :
class Post(models.Model):
title = models.CharField(max_length=50)
body = RichTextField(blank=True, null=True)
date = models.DateTimeField('date_posted')
username = models.ForeignKey(admin.username, on_delete=models.CASCADE)
Where admin.username refers the username of auth_user admin model
Thanks for your help
As the referencing the user model section of the documentation says, you can make use of settings.AUTH_USER_MODEL to obtain a reference to the user model that is used. You can use the to_field=… [Django-doc] to specify to what field of the model it should refer, so:
from django.conf import settings
class Post(models.Model):
title = models.CharField(max_length=50)
body = RichTextField(blank=True, null=True)
date = models.DateTimeField('date_posted')
author = models.ForeignKey(
settings.AUTH_USER_MODEL,
to_field='username'
on_delete=models.CASCADE,
editable=False
)
By specifying editable=False [Django-doc] it will not automatically show up in ModelForms.
In views, you can then set the logged in user as author by specifing the author attribute. For example:
from django.contrib.auth.decorators import login_required
from django.shortcuts import redirect
#login_required
def some_view(request):
if request.method == 'POST':
form = PostForm(request.POST)
if form.is_valid():
form.instance.author = request.user
form.save()
return redirect('name-of-some-view')
else:
form = PostForm()
return render(request, 'some_template.html', {'form': form})
Note: A ForeignKey does not store the string representation (or name) of the
referenced object in the column, it stores the primary key of the record it
references in a column with an _id suffix to a ForeignKey field. Therefore
ForeignKeys usually do not end with a _name suffix. You might want to
consider renaming the username field to author.
How about something like this?
class Post(models.Model):
title = models.CharField(max_length=50)
body = RichTextField(blank=True, null=True)
date = models.DateTimeField('date_posted')
user = models.ForeignKey(auth_user, on_delete=models.CASCADE)
#property
def username(self): return self.user.username
Usage:
some_post = Post.objects.get(id='the_post_id')
print(some_post.username) # prints some_post.user.username
How can I create a relationship between my object and foreign key from a form submit? You can skip down to the very last line of code to see my issue.
edit
My user will not have an option to select the related model object. The related model object will be exclusively the one identified by the id which is determined from the URL, i.e. domain.com/myview/100
models.py
class Activity(models.Model):
id = models.AutoField(primary_key=True)
class Contact(models.Model):
id = models.AutoField(primary_key=True)
firstname = models.CharField(max_length=100, null=False, blank=False)
activity = models.ManyToManyField(Activity, blank=True)
forms.py
class ContactForm(forms.ModelForm):
firstname = forms.CharField(max_length=100,
widget=forms.TextInput(attrs={'placeholder':'John'}))
class Meta:
model = Contact
views.py
def index(request, id=None):
if id:
if request.method == 'POST':
contact_form = ContactForm(request.POST)
if contact_form.is_valid():
contact = contact_form.save()
# link contact to activity here, activity pk is 'id'
I finally see what are you trying to do, it's pretty easy:
contact = contact_form.save()
# link contact to activity here, activity pk is 'id'
activity = Activity.objects.get(id=id)
contact.activity.add(activity)
I was confused before because you have id as view function parameter, which people usually use to update a contact because you also have a ContactForm in views.py method. You might make it more explicit using activity_id instead, and make the function name more explicit as well.
I want the users, once they are logged in, to be able to add information about their company including website, name, logo, etc.
I already have this model
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, unique=True)
comp_name = models.CharField(max_length=120,default='', blank=True)
comp_site = models.URLField(default='', blank=True)
comp_logo = models.ImageField(default='', blank=True, upload_to='img/logos/')
in my views.py I have this:
if form1.is_valid():
saveInfo = form1.save(commit=False)
comp_name = form1.cleaned_data.get("comp_name")
comp_site = form1.cleaned_data.get("comp_site")
comp_logo = form1.cleaned_data.get("comp_logo")
saveInfo.user = form1.user
saveInfo.save()
return redirect('/profil/')
What I'd like is that the program would automatically detects which user is currently logged in, and set the user field to that user.
How could I do this?
The request attribute sent with any Django specifies the current user.
def myview(request):
current_user = request.user
You can check if the user is logged in using the request.user.is_authenticated() method. What I would do here is redirect the login view to the view with your form. This should automatically happen if you are using #login_required on the form view.
As an aside, if you are extending the User model, you should use OneToOneField instead of ForiegnKey. Use ForiegnKeyonly if each user can have multiple companies.
if form1.is_valid():
saveInfo = form1.save(commit=False)
comp_name = form1.cleaned_data.get("comp_name")
comp_site = form1.cleaned_data.get("comp_site")
comp_logo = form1.cleaned_data.get("comp_logo")
saveInfo.user = request.user #<--- the authenticated user bound to the current request
saveInfo.save()
return redirect('/profil/')
request.user is the current user who is bound to the current request. You must (probably you already do) check if user is authenticated etc..
You can associate the users to a model using one to one field as shown below
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User, null=True, on_delete=models.CASCADE)
bio = models.TextField()
organisation = models.CharField(max_length=300, default="")
country = models.CharField(max_length=50, default="")
display_pic = models.ImageField(upload_to="authors/profile", default="")
You can then get their info of user using 'Profile' and 'User'
I'm using django's built-in contrib.auth module and have setup a foreign key relationship to a User for when a 'post' is added:
class Post(models.Model):
owner = models.ForeignKey('User')
# ... etc.
Now when it comes to actually adding the Post, I'm not sure what to supply in the owner field before calling save(). I expected something like an id in user's session but I noticed User does not have a user_id or id attribute. What data is it that I should be pulling from the user's authenticated session to populate the owner field with? I've tried to see what's going on in the database table but not too clued up on the sqlite setup yet.
Thanks for any help...
You want to provide a "User" object. I.e. the same kind of thing you'd get from User.objects.get(pk=13).
If you're using the authentication components of Django, the user is also attached to the request object, and you can use it directly from within your view code:
request.user
If the user isn't authenticated, then Django will return an instance of django.contrib.auth.models.AnonymousUser. (per http://docs.djangoproject.com/en/dev/ref/request-response/#attributes)
Requirements --> Django 3, python 3
1) For add username to owner = models.ForeignKey('User') for save that, in the first step you must add from django.conf import settings above models.py and edit owner = models.ForeignKey('User') to this sample:
class Post(models.Model):
slug = models.SlugField(max_length=100, unique=True, null=True, allow_unicode=True)
owner = models.ForeignKey(settings.AUTH_USER_MODEL, default=1, on_delete=models.CASCADE)
2) And for show detail Post, special owner name or family or username under the post, you must add the following code in the second step in views.py:
from django.shortcuts import get_object_or_404
.
.
.
def detailPost(request,slug=None):
instance = get_object_or_404(Post, slug=slug)
context = {
'instance': instance,
}
return render(request, template_name='detail_post.html', context=context)
3) And in the third step, you must add the following code for show user information like user full name that creates a post:
<p class="font-small grey-text">Auther: {{ instance.owner.get_full_name }} </p>
now if you want to use user name, you can use {{ instance.owner.get_username }}
or if you want to access short name, you can use {{ instance.owner.get_short_name }}.
See this link for more information.