how to add a friend system to django - html

I have been trying to add a friend system to django in which the user can add and remove friends, in the process I found a Friend matching query does not exist error and shows that this part of the code is bad:
friend = Friend.objects.get(current_user=request.user)
now here I will leave the complete code.
views.py
def profile(request, username=None):
friend = Friend.objects.get(current_user=request.user)
friends = friend.users.all()
if username:
post_owner = get_object_or_404(User, username=username)
user_posts=Post.objects.filter(user_id=post_owner)
else:
post_owner = request.user
user_posts=Post.objects.filter(user=request.user)
args1 = {
'post_owner': post_owner,
'user_posts': user_posts,
'friends': friends,
}
return render(request, 'profile.html', args1)
def change_friends(request, operation, pk):
friend = User.objects.get(pk=pk)
if operation == 'add':
Friend.make_friends(request.user, friend)
elif operation == 'remove':
Friend.lose_friends(request.user, friend)
return redirect('profile')
models.py
class Friend(models.Model):
users = models.ManyToManyField(User, default='users', blank=True, related_name='users')
current_user = models.ForeignKey(User, related_name='owner', on_delete=models.CASCADE, null=True)
#classmethod
def make_friend(cls, current_user, new_friend):
friend, created = cls.objects.get_or_create(
current_user=current_user
)
friend.users.add(new_friend)
#classmethod
def lose_friend(cls, current_user, new_friend):
friend, created = cls.objects.get_or_create(
current_user=current_user
)
friend.users.remove(new_friend)
if the profile.html is neede please let me know:)

request.user has no Friend record as the error indicates. You can simple change the get operation to filter&first operations. Friend.objects.filter(current_user=request.user).first() then do not forget to check friend instance exists. So your view should be something like:
def profile(request, username=None):
friend = Friend.objects.filter(current_user=request.user).first()
friends = []
if friend:
friends = friend.users.all()
if username:
post_owner = get_object_or_404(User, username=username)
user_posts = Post.objects.filter(user_id=post_owner)
else:
post_owner = request.user
user_posts = Post.objects.filter(user=request.user)
args1 = {
'post_owner': post_owner,
'user_posts': user_posts,
'friends': friends,
}
return render(request, 'profile.html', args1)

Related

Edit a foreign key's fields in a template

I'm unsure of how I can edit a foreign key's fields from the template of another model - my changes do not update the model on post, see below.
models
class Projects(models.Model):
name = models.CharField(max_length=250)
class Current(models.Model):
fk_user = models.OneToOneField(User, on_delete=models.CASCADE)
fk_project = models.ForeignKey(projects, default='1', on_delete=models.CASCADE)
views
class current(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Current
fields = [
'fk_project'
]
template_name = 'users/current.html'
context_object_name = 'current'
def form_valid(self, form):
form.instance.fk_user = self.request.user
form.save()
# return super().form_valid(form)
return HttpResponseRedirect(self.request.path_info)
def test_func(self):
post = self.get_object()
if self.request.user == post.fk_user:
return True
return False
current.html
<form method="POST">{% csrf_token %}
<input type="text" value="{{ current.fk_project.name }}"/>
<button type="submit">post</button>
I would suggest you amend form_valid to follow the usual conventions. No idea if this will fix it, but
def form_valid(self, form):
instance = form.save( commit=False)
instance.fk_user = self.request.user
instance.save()
# return super().form_valid(form)
return HttpResponseRedirect(self.request.path_info)
If the desire is to update fields in the Project which is identified by the form as well as to store it in the Current instance which is the subject of this UpdateView, you can accomplish this by adding appropriate non-Model fields to the form and then processing the data in form_valid. For example, to pick a project, link it as at present, and simultaneously update its name:
class CurrentAndProjectUpdateForm( forms.ModelForm):
class Meta:
model = Current
fields = ['fk_project', ]
name = forms.CharField( ...) # new name for the related project
class current(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
model = Current # don't think this now necessary
form_class = CurrentAndProjectUpdateForm # because it's implicit in this form
# fields = # DEFINITELY not needed here now
...
def form_valid(self, form):
instance = form.save( commit=False)
instance.fk_user = self.request.user
instance.save()
project = instance.fk_project
project.name = form.cleaned_data['name']
project.save()
# return super().form_valid(form)
return HttpResponseRedirect(self.request.path_info)

How to make Django views require a user login?

I have a Django project with a login screen; when I enter my username and password I get directed to the home page. This works fine! But nothing is secure, I can just go to the view at /allstudyplans without logging in and see all the information there. My Question is how do I make it so it's not possible to go /allstudyplans without logging in first?
Form
User = get_user_model()
class UserLoginForm(forms.Form):
username = forms.CharField(label='', widget=forms.TextInput(
attrs={
'class': 'form-control',
'autofocus': '',
'placeholder': 'Användarnamn',
}
), )
password = forms.CharField(label='', widget=forms.PasswordInput(
attrs={
'class': 'form-control mt-1',
'placeholder': 'Lösenord',
}
), )
# https://docs.djangoproject.com/en/2.1/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other
def clean(self):
cleaned_data = super().clean()
username = cleaned_data.get('username')
password = cleaned_data.get('password')
if username and password:
user = authenticate(username=username, password=password)
if not user:
raise forms.ValidationError(
'Oh! I can\'t find that user - create user first!')
elif not user.check_password(password):
raise forms.ValidationError(
'Oh! That password is incorrect - try again!')
elif not user.is_active:
raise forms.ValidationError(
'Oh! That user is not active in the database!')
Views
def home(request):
next = (request.GET.get('next'))
form = UserLoginForm(request.POST or None)
if form.is_valid():
username = form.cleaned_data.get('username')
password = form.cleaned_data.get('password')
user = authenticate(username=username, password=password)
login(request, user)
if next:
return redirect(next)
return redirect('/')
context = {
'form': form,
}
return render(request, "utility-login.html", context)
def Assignments(request):
return render(request, 'nav-side-team.html')
def DetailAssignment(request):
obj = Assignment.objects.all()
context = {
'object': obj
}
return render(request, 'nav-side-project.html', context)
def studyplans(request):
return render(request, 'allStudyplans.html')
def detailStudyplan(request):
return render(request, 'detailStudyplan.html')
Also a Home View in the normal project file (not the app)
#login_required
def homee(request):
return render(request, "allstudyplans.html", {})
Urls in the project:
urlpatterns = [
path('admin/', admin.site.urls),
path('account/', include('accounts.urls')),
path('', include('accounts.urls'))
]
Urls in the app:
urlpatterns = [
path('', views.studyplans),
path('login', views.home),
path('nav-side-team.html', views.Assignments),
path('nav-side-project.html', views.DetailAssignment),
path('allstudyplans.html', views.studyplans),
path('detailStudyplan.html', views.detailStudyplan),
]
Tried this:
#login_required
def Assignments(request):
if not request.user.is_authenticated:
return redirect('%s?next=%s' % ('utility-login.html', request.path))
return render(request, 'nav-side-team.html')
studyplans is missing the decorator login_required.
According to the docs, https://docs.djangoproject.com/en/2.2/topics/auth/default/#the-login-required-decorator, the easiest way should be
#login_required
def studyplans(request):
return render(request, 'allStudyplans.html')
Another way to do it – probably equivalent to the above – is with "mixins":
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
class MyView(LoginRequiredMixin, View):
...
Notice that "mixin" class names should occur first in the list, before View.
(Notice that I also show that there's a "permission-required mixin.")
I guess it just comes down to personal preference, and consistency with the existing source-code of the application.

How do a make a login feature that retrieves the user from the database?

I am making a basic web page that has a sign up page and a login page. I am using google app engine, python, and HTML. This is my user function:
class User(db.Model):
name = db.StringProperty(required=True)
pw_hash = db.StringProperty(required=True)
email = db.StringProperty()
#classmethod
def by_id(cls, uid):
return cls.get_by_id(uid, parent=users_key())
#classmethod
def by_name(cls, name):
u = cls.all().filter('name=', name).get()
return u
#classmethod
def register(cls, name, pw, email=None):
pw_hash = make_pw_hash(name, pw)
return cls(parent=users_key(),
name=name,
pw_hash=pw_hash,
email=email)
#classmethod
def login(cls, name, pw):
u = cls.by_name(name)
if u and valid_pw(name, pw, u.pw_hash):
return u
When I register new users, I put them in the database. They are being stored in the database:
class Register(Signup):
def done(self):
#make sure the user doesn't already exist
u = User.by_name(self.username)
if u:
msg = 'That user already exists.'
self.render('signup-form.html', error_username = msg)
else:
u = User.register(self.username, self.password, self.email)
u.put()
self.login(u)
self.redirect('/blog')
But when I use my login function, I am unable to retrieve the user from the database to use the login feature. It says "login invalid" every time:
class Login(BlogHandler):
def get(self):
self.render('login-form.html')
def post(self):
username = self.request.get('username')
password = self.request.get('password')
u = User.login(username, password)
if u:
self.login()
self.redirect('/blog')
else:
msg = 'Invalid login'
self.render('login-form.html', error = msg)
When I signup, it's supposed to recognize that the User is already in the database. However, I am able to sign up with the same credentials every time. Here is my signup Handler:
class Signup(BlogHandler):
def get(self):
self.render("signup-form.html")
def post(self):
have_error = False
self.username = self.request.get('username')
self.password = self.request.get('password')
self.verify = self.request.get('verify')
self.email = self.request.get('email')
params = dict(username = self.username,
email = self.email)
if not valid_username(self.username):
params['error_username'] = "That's not a valid username."
have_error = True
if not valid_password(self.password):
params['error_password'] = "That wasn't a valid password."
have_error = True
elif self.password != self.verify:
params['error_verify'] = "Your passwords didn't match."
have_error = True
if not valid_email(self.email):
params['error_email'] = "That's not a valid email."
have_error = True
if have_error:
self.render('signup-form.html', **params)
else:
self.done()
def done(self, *a, **kw):
raise NotImplementedError
Here is the bloghandler function which is the base line for all the other functions:
class BlogHandler(webapp2.RequestHandler):
def write(self, *a, **kw):
self.response.out.write(*a, **kw)
def render_str(self, template, **params):
params['user'] = self.user
return render_str(template, **params)
def render(self, template, **kw):
self.write(self.render_str(template, **kw))
def set_secure_cookie(self, name, val):
cookie_val = make_secure_val(val)
self.response.headers.add_header(
'Set-Cookie',
'%s=%s; Path=/' % (name, cookie_val))
def read_secure_cookie(self, name):
cookie_val = self.request.cookies.get(name)
return cookie_val and check_secure_val(cookie_val)
def login(self, user):
self.set_secure_cookie('user_id', str(user.key().id()))
def logout(self):
self.response.headers.add_header('Set-Cookie', 'user_id=; Path=/')
def initialize(self, *a, **kw):
webapp2.RequestHandler.initialize(self, *a, **kw)
uid = self.read_secure_cookie('user_id')
self.user = uid and User.by_id(int(uid))
Here is the link to the GITHUB:
https://github.com/keldavis/registration
Here is the link to the website:
registration-148718.appspot.com
How do I make my signup page recognize an already created user? And how can I make my login page retrieve my user from the database and perform a valid login?
Your line
u = cls.all().filter('name=', name).get()
should either be
u = cls.all().filter('name =', name).get()
or
u = cls.all().filter('name', name).get()
per Google docs (note the missing space character / the = character being optional):
property_operator: String consisting of a property name and an optional comparison
operator (=, !=, <, <=, >, >=, IN), separated by a space: for example,
'age >'. If just a property name is specified without a comparison
operator, the filter compares for equality (=) by default.
(also note that you should be using google.appengine.ext.ndb instead of google.appengine.ext.db and really shouldn't be implementing authentication / authorization / hashing / etc on your own in real apps)

Working with sorl-thumbnail and Django Admin

I get this error "employee_directory.thumbnail_kvstore' doesn't exist" when I use sorl-thumbnail to try and format my django admin profile image. Has anyone ran into this while working with sorl-thumbnail and django admin changelist?
DatabaseError at /directory/employee/
(1146, "Table 'employee_directory.thumbnail_kvstore' doesn't exist")
I doubled checked my sorl-thumbnail installation, and made sure I did a syncdb. Below is the code from my models.py and admin.py
models.py:
from django.db import models
from sorl.thumbnail import ImageField
# Department Table
class Department(models.Model):
department_name = models.CharField(max_length=128)
def __unicode__(self):
return self.department_name
# Employee Directory Table
class Employee(models.Model):
last_name = models.CharField(max_length=32)
first_name = models.CharField(max_length=32)
profile_image = models.ImageField(upload_to="images/profile_image", blank=True)
department_name = models.ForeignKey('Department')
job_title = models.CharField(max_length=64)
office_number = models.CharField(max_length=8, blank=True)
fax_number = models.CharField(max_length=8, blank=True)
mobile_number = models.CharField(max_length=8, blank=True)
intercom_number = models.CharField(max_length=3, blank=True)
email = models.CharField(max_length=128)
memo = models.TextField(blank=True)
def __unicode__(self):
return self.last_name + ', ' + self.first_name
admin.py:
from directory.models import *
from django.contrib import admin
from sorl.thumbnail import get_thumbnail
class EmployeeAdmin(admin.ModelAdmin):
def profile_img(self, obj):
if obj.profile_image:
t = get_thumbnail(obj.profile_image,"50x50",crop='center', quality=99)
return u'<img src="/media%s"/>' % t.url
else:
return u'profile_image'
profile_img.short_description = 'Profile image'
profile_img.allow_tags = True
search_fields = ['last_name', 'first_name']
list_display = ['profile_img', 'last_name', 'first_name', 'department_name',
'job_title', 'office_number', 'fax_number',
'mobile_number', 'intercom_number', 'email']
list_filter = ['department_name']
admin.site.register(Department)
admin.site.register(Employee, EmployeeAdmin)
Any help is greatly appreciated.
I totally noobed out, I forgot to put sorl.thumbnail in my apps in the django settings.

Django Extended User Profile Sign Up Form Returns IntegrityError

So, I'm new to Django and this has become a major headache. So I'm trying to create an extended user profile a la the documentation. However, when I attempt to post an entry through the form I receive the following error:
Exception Type: IntegrityError at /signup/ Exception Value: (1062,
"Duplicate entry '64' for key 2")
Upon crashing with an Internal Server Error, I notice that a new user with the relevant fields (username, password, first name, last name) is created and so is the profile entry. However the profile entry is devoid of all the information entered, with the exception of the id of the user the profile is associated with. Here is the relevant code:
In views.py:
from django.shortcuts import render_to_response
from django.template import RequestContext
from portalman.models import FnbuserForm, AuthUserForm, Fnbuser
from django.http import HttpResponseRedirect
from django.core.context_processors import csrf
from django.db import IntegrityError
from django.utils.safestring import mark_safe
from django.contrib.auth.models import User
def signup(request):
viewParam = {}
errors = None
profileForm = FnbuserForm()
userForm = AuthUserForm()
if request.method == "POST":
profileForm = FnbuserForm(request.POST)
userForm = AuthUserForm(request.POST)
if userForm.is_valid() and profileForm.is_valid():
newuser = User.objects.create_user(userForm.cleaned_data['username'], userForm.cleaned_data['email'], userForm.cleaned_data['password'])
newuser.first_name = userForm.cleaned_data['first_name']
newuser.last_name = userForm.cleaned_data['last_name']
newuser.save()
newFnbUser = Fnbuser(user = newuser, #other profile elements#)
newFnbUser.save()
return HttpResponseRedirect('/thanks/')
else:
profileForm = FnbuserForm() # An unbound profile form
userForm = AuthUserForm() #An unbound user form
else:
viewParam = {'profileForm': profileForm, 'userForm' : userForm, 'links' : links}
viewParam.update(csrf(request))
return render_to_response('signup.html', viewParam, context_instance=RequestContext(request))
In portalman/models.py:
from django.db import models
from django import forms
from django.contrib.auth.models import User, UserManager
from django.db.models.signals import post_save
class Fnbuser(models.Model):
telephone = models.CharField(max_length=20, blank=True, null=True)
additionalNotes = models.TextField(help_text=("Feel free to add additional notes or comments here!"), blank=True,
verbose_name="Notes", null=True)
canCook = models.BooleanField(verbose_name="Can Cook", default=False, blank=True)
canTransport = models.BooleanField(verbose_name="Can Tranport", default=False, blank=True)
canServe = models.BooleanField(verbose_name="Can Serve Food", default=False, blank=True)
canGarden = models.BooleanField(verbose_name="Can Garden", default=False, blank=True)
canProgram = models.BooleanField(verbose_name="Can Program", default=False, blank=True)
canDesign = models.BooleanField(verbose_name="Can Design", default=False, blank=True)
canAlso = models.CharField(verbose_name="Other", max_length=255, blank=True, null=True)
user = models.ForeignKey(User, unique=True)
def __str__(self):
return self.user.username
def create_user_profile(sender, instance, created, **kwargs):
if created:
Fnbuser.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User)
class Meta:
verbose_name = "Food Not Bombs User"
verbose_name_plural = "Food Not Bombs Users"
class AuthUserForm(forms.Form):
username = forms.RegexField(label=("*Username:"), max_length=30, regex=r'^[\w.#+-]+$',
error_messages = {'invalid': ("This value may contain only letters, numbers and # . + - _ characters."),
'inUse' : ("This username is already in use, try another.")},
help_text = ("Required. 30 characters or fewer. Letters, digits and # . + - _ only."))
password = forms.CharField(label=("*Password:"), widget=forms.PasswordInput,
help_text = ("Required. 30 characters or fewer. Letters, digits and # . + - _ only."),
error_messages = {'invalid': ("This value may contain only letters, numbers and # . + - _ characters.")})
email = forms.CharField(label=("E-Mail Address:"), required=False)
first_name = forms.CharField(label=("First Name:"), required=False)
last_name = forms.CharField(label=("Last Name:"), required=False)
class FnbuserForm(forms.Form):
telephone = forms.CharField(label=("Telephone:"), required=False)
additionalNotes = forms.CharField(label=("Additional Notes about yourself, or general comments."),
widget = forms.widgets.Textarea(), required=False)
canCook = forms.BooleanField(label=("Can Help Cook:"), required=False)
canTransport = forms.BooleanField(label=("Can Help Transport:"), required=False)
canServe = forms.BooleanField(label=("Can Help Serve Food:"), required=False)
canGarden = forms.BooleanField(label=("Can Help Garden:"), required=False)
canProgram = forms.BooleanField(label=("Can Help Program Site:"), help_text=("""If you can help program the site,
note what languages you can program in within the "can also help with" box."""), required=False)
canDesign = forms.BooleanField(label=("Can Help With Design:"), help_text=("""Photography/Video Editing/Web Design/etc. Note
what you can do specifically within the "can also help with" box."""), required=False)
canAlso = forms.CharField(label=("Can Also Help With:"), required=False)
class Meta:
model=Fnbuser
Could anyone suggest what is going wrong? I would be very grateful!
You can't use:
Fnbuser.objects.create(user=instance)
after the object has already been created with:
newFnbUser.save()
That's why the call to the create method in the QuerySet (objects) will raise IntegrityError.
see doc