i have two model which are Post and Profile. i am keepin blog datas which are title,body,owner,slug etc in Post. and keepin' user profile settings which are slogan,email,website etc. in Profile
in my index.html page i display user profile infos and post lists in same page. so ;
i need to connect these two models each other. when someone goes to 127.0.0.1/blog/username (with or without login) all the data which are belong to user named 'username' must be there.
here is my models.py:
class Profile(models.Model):
slogan = models.TextField(blank=True)
twitter = models.CharField(max_length = 100,blank=True)
web_site = models.CharField(max_length=100,blank=True)
email = models.CharField(max_length = 100,blank=True)
def __unicode__(self):
return self.slogan
class Post(models.Model):
owner = models.ForeignKey(User)
title = models.CharField(max_length = 100)
body = models.TextField()
bodyPreview = models.TextField() #preview için body alanı
titlePreview = models.CharField(max_length=100) # preview için title alanı
slug = AutoSlugField(populate_from='title' ,unique=True)
posted = models.DateField(auto_now_add=True)
isdraft = models.BooleanField(default=False)
def __unicode__(self):
return self.title
#permalink
def get_absolute_url(self):
return ('view_blog_post',None,{'postslug':self.slug})
and my index view :
def index(request,username):
post_list = Post.objects.filter(owner__username=username).filter(isdraft=False).order_by("-posted")
p_index = Paginator(post_list,3) #anasayfa için pagination.[her sayfada 3 post]
page = request.GET.get('page')
try:
indexPag = p_index.page(page)
except PageNotAnInteger:
indexPag = p_index.page(1)
except EmptyPage:
indexPag = p_index.page(p_index.num_pages)
## i need to get user's profile datas here. ??
return render_to_response('index.html',
{'post_list':post_list,'p_index':indexPag,'profile':query},
context_instance = RequestContext(request))
I think you should change your Profile model and add a OneToOne relationship to the User model(for more info see here):
class Profile(models.Model):
user = models.OneToOneField(User)
...
class Posts(models.Model):
author = models.ForeignKey(User)
...
and then in your views you can do:
user = get_object_or_404(User, username=username)
post_list = Post.objects.filter(author=user).filter(isdraft=False).order_by("-posted")
return render_to_response('index.html',
{'post_list': post_list, 'user': user, ...}, ...)
And then in your template you are able to access the user's profile.More here
e.g {{user.get_profile.slogan}}
In your view:
def index(request, username):
user = User.objects.get(username=username)
return render(request, 'index.html', {'user':user})
In your template:
{{ user.post_set }}
and You will receive list of posts of current user.
The most natural way to achieve that is to add a OneToOne relation between your Profile model and the django's User model.
from django.contrib.auth.models import User
class Profile(models.Model):
user = models.OneToOneField(User)
# More fields
class Article(models.Model):
author = models.ForeignKey(User)
# More fields
This way, you can access the profile data through a User object. Would be something like this:
user = User.objecets.get(username=username)
profile = user.profile
More info about this, you can read the django model fields documentation here
and you can also see this cool answer about the diference between the ForeignKey with unique=True and the OneToOneField
I hope this helps
Related
I'm trying to create a todoapp with google login to create personal todolist for each users.
here's views.py
from django.contrib.auth.decorators import login_required
#login_required
def todoView(request):
all_todo_items = Todoitem.objects.filter(userid=request.user.id)
return render(request, 'todoapp/home.html', {'all_items': all_todo_items})
def addTodo(request):
add_new_item = Todoitem(content=request.POST['content'])
add_new_item.save()
return HttpResponseRedirect('/home/')
this is my code before without users but when there's currently login user it's throwing this error
null value in column "id" violates not-null constraint / DETAIL: Failing row contains (null, sampletodo,null). I believe the third column which is null is the userid and first column null is auto increment id since I set it to id SERIAL primary key in todoitem table
I'm 100% sure i need to add something #addTodo views.py, I just dont know how to add todolist with the current user
EDIT here's my models.py
class Todoitem(models.Model):
content = models.CharField(max_length=100)
userid = models.ForeignKey(AuthUser, models.DO_NOTHING,
db_column='userid')
class Meta:
managed = False
db_table = 'todoitem'
class AuthUser(models.Model):
password = models.CharField(max_length=128)
last_login = models.DateTimeField(blank=True, null=True)
is_superuser = models.BooleanField()
username = models.CharField(unique=True, max_length=150)
soon...
class Meta:
managed = False
db_table = 'auth_user'
Just pass the current user the same way you did in todoView. The request object has a reference to the current user through request.user. But you need to specify the user object, not user.id
#login_required
def todoView(request):
all_todo_items = Todoitem.objects.filter(userid=request.user) # changed to request.user
return render(request, 'todoapp/home.html', {'all_items': all_todo_items})
def addTodo(request):
add_new_item = Todoitem(content=request.POST['content'], userid=request.user)
add_new_item.save()
return HttpResponseRedirect('/home/')
You should use a good user model to be able to use request.user.
Try a model like this:
from django.contrib.auth.models import AbstractUser
class User(AbstractUser):
password = models.CharField(max_length=128)
last_login = models.DateTimeField(blank=True, null=True)
is_superuser = models.BooleanField()
username = models.CharField(unique=True, max_length=150)
then in your views you can do this
def addTodo(request):
add_new_item = Todoitem(content=request.POST['content'], userid=request.user)
def todoView(request):
all_todo_items = Todoitem.objects.filter(userid=request.user) # changed to request.user
return render(request, 'todoapp/home.html', {'all_items': all_todo_items})
I have created the user authentication system which includes both the default User model and an extended User model. They are as below:
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import User
class UserProfile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True)
Photo = models.ImageField(upload_to='documents/%Y/%m/%d/', null=True)
uploaded_at = models.DateTimeField(auto_now_add=True, null=True)
dob = models.DateField(max_length=20, null=True)
country = models.CharField(max_length=100, null=True)
State = models.CharField(max_length=100, null=True)
District = models.CharField(max_length=100, null=True)
phone = models.CharField(max_length=10, null=True)
def get_absolute_url(self):
return reverse('profile', kwargs={'id': self.id})
forms.py
class UserProfileForm(forms.ModelForm):
Photo = forms.ImageField( max_length=100)
dob = forms.DateField(widget=forms.TextInput(attrs={'type': 'date'}))
country = forms.CharField(max_length=100)
State = forms.CharField(max_length=100)
District = forms.CharField(max_length=100)
phone = forms.CharField(max_length=10)
class Meta:
model = UserProfile
fields = ('Photo', 'dob', 'country', 'State', 'District', 'phone')
With the help of the above model and form, I am able to create user, and enter values for those custom model fields and see the user profile. So far so good.
However, I am facing issues while I update those custom fields. I have used the Django's in-built modules to update the default User fields(email). But I am not able to find a way to update those custom fields('dob', 'country', 'State', 'District', 'phone'). Below is the method from views.
views.py
#login_required(login_url="/login/")
def editUserProfile(request):
if request.method == "POST":
form = UserProfileUpdateForm(request.POST, instance=request.user) # default User profile update
obj = UserProfile.objects.get(id=request.user.id)
form1 = UserProfileForm(request.POST or None, instance=obj) # custom fields update.
if form.is_valid() and form1.is_valid():
obj.Photo = form1.cleaned_data['Photo']
obj.dob = form1.cleaned_data['dob']
obj.country = form1.cleaned_data['country']
obj.State = form1.cleaned_data['State']
obj.District = form1.cleaned_data['District']
obj.phone = form1.cleaned_data['phone']
form.save()
form1.save()
messages.success(request, f'updated successfully')
return redirect('/profile1')
else:
messages.error(request, f'Please correct the error below.')
else:
form = UserProfileUpdateForm(instance=request.user)
form1 = UserProfileUpdateForm(instance=request.user)
return render(request, "authenticate\\editProfilePage.html", {'form': form, 'form1': form1})
I have an update button on my profile page, on clicking I could only see the "email" field with pre-populated data to update(I can update this default field successfully).
I have seen other stackoverflow posts, but they are not helping.
I am not able to figure out the mistakes.
Please help
Thank you,
I think the problem is in this line
obj = UserProfile.objects.get(id=request.user.id)
here left id is id from UserProfile model. so it will be something like this
obj = UserProfile.objects.get(user__id=request.user.id)
I am trying using django forms and not model forms. While trying to populate data for edit I keep getting keyError (u 'manager'). This does not appear if I remove assignment of a field 'choices'. Choice is a many to many field on my model. to make it less confusing I will paste my model, forms and view.
#model.py
class Choices(models.Model):
choices = models.CharField(max_length=70)
def __unicode__(self):
return self.choices
class UserProfile(models.Model):
user = models.OneToOneField(MyUser)
about_me = models.TextField(max_length=2000, null=True, blank=True)
country = models.CharField(max_length=100,null=True, blank=True)
choices = models.ManyToManyField(Choices, blank=True)
#forms.py
class UserProfileForm(forms.Form):
CHOICES = (
('like to cook', 'like to cook'),
('like only to eat', 'like only to eat')
)
about_me = forms.CharField(widget=forms.Textarea, required=False)
country = forms.CharField(max_length=60,required=False)
choices =forms.MultipleChoiceField(choices=CHOICES,widget=forms.CheckboxSelectMultiple(),required=False)
#views.py
#login_required
def update_profile(request):
userprofile = UserProfile.objects.get(user=request.user)
form = UserProfileForm(initial={'about_me':userprofile.about_me,
'country':userprofile.country,
'choices': userprofile.choices})
return render(request, 'u_profiles/edit_pro.html', {'form':form})
now when I assign the initial value of selected choices I get the keyerror. I would like to know the correct way of doing this.
Thanks.
I have a list of employees who work at a site. Each site is owned by a User (using Django's standard user model).
I want to create a form that adds an employee and automatically links them to a site dependent on who the authenticated user is:
models.py:
class Employee(models.Model):
site = models.ForeignKey(Site, null=True)
employee_name = models.CharField(default='name', max_length=128, blank=False, null=False)
class Site(models.Model):
user = models.ForeignKey(User)
site_name = models.CharField(max_length=128, blank=False, null=False)
views.py:
site_profile = Site.objects.get(user=request.user)
if request.method == "POST":
form = EmployeeAddForm( request.POST )
if form.is_valid():
obj = form.save(commit=False)
obj.site = site_profile
obj.save()
return redirect('dashboard_home')
form = EmployeeAddForm()
return render(request, "dashboard/employees.html", {'form': form })
forms.py:
class EmployeeAddForm(forms.ModelForm):
class Meta:
model = Employee
fields = ( 'employee_name')
This code will add the employee to the database, but in django admin, list_display = 'site' results in Site object not the actual site name. It does not appear that the employee is linked to the site.
If I use obj.site = site_profile.id (adding .id), I get the error Cannot assign "1": "Employee.site" must be a "Site" instance.
Found the error: the above code is correct, I simply had a tab ordering error in my Site modeL
class Site(models.Model):
...
def __str__(self):
return self.site_name
def should have been inserted 1 tab inwards.
My creation is a basic project about ticketing, users and assets. It's a typical application that companies have to keep a list of who has what and what issues are occurring.
So far I have (models):
**** Tickets ******************
class Ticket(models.Model):
category = models.ForeignKey('TicketCategory')
issue = models.CharField(max_length=100)
user = models.ForeignKey('Users', blank=True,null=True,related_name="tickets")
owner = models.ForeignKey(User)
**** Users *********************
class Users(models.Model):
firstname = models.CharField(max_length=100)
lastname = models.CharField(max_length=100)
email = models.CharField(max_length=100, blank=True)
business = models.ForeignKey('Business', blank=True, null=True,related_name="users")
owner = models.ForeignKey(User)
class Meta:
db_table = 'users'
verbose_name_plural = "users"
ordering = ["lastname"]
**** Assets *********************
class Assets(models.Model):
serial = models.CharField(unique=False, max_length=100)
brand = models.CharField(max_length=100)
user = models.ForeignKey('Users', blank=True, null=True, related_name="assets")
location = models.ForeignKey('AssetLocation', blank=False, null=False, related_name="assets")
owner = models.ForeignKey(User)
I have stripped them down a bit to exclude the useless info. There are others also like AssetsLocations, Categories etc., all of them in the same pattern - the owner is added in the end as a Foreign Key.
I have created some form of authentication, so every logged in user will have his own tickets, assets, and users (employees actually). Filtering is needed so the data of each user ONLY are displayed after every successful authentication.
I am using CBVs and override the get_queryset to enable filtering by the user currently logged in:
Views.py
class TicketList(ListView):
template_name = 'assets/ticket_list.html'
def get_queryset(self):
user = self.request.user
return Ticket.objects.filter(owner_id=user.id).select_related('user','asset','category')
def get_context_data(self, **kwargs):
context = super(TicketList, self).get_context_data(**kwargs)
context['totalTickets'] = self.get_queryset().count()
context['tickets'] = self.get_queryset().select_related('user','asset','category')
return context
Everything works successfully and only logged_in user's data are shown. Then I am trying to create a new Ticket:
class TicketCreate(CreateView):
fields = [ 'category', 'issue', 'user']
template_name = 'assets/ticket_form.html'
def get_queryset(self):
user = self.request.user
return Ticket.objects.filter(owner_id=user.id)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.owner_id = self.request.user.id
self.object.save()
return HttpResponseRedirect(self.get_success_url())
success_url = reverse_lazy('ticket_list')
I am getting everything posted in the form template by using {{ form.category }}, {{ form.issue }} etc. The issue I am facing is that the drop-down boxes displayed in the form, for example the {{ form.user }} should be displaying only the users where user.owner = self.request.user.id, in simple words: the users that the owner created. Instead of it, all the users in the database are displayed.
Isn't it obvious which is the question :) ?