Yet another No Reverse Match - python

I have impletmented the detailview with views.py this afternoon.
I have a model with the pk set as a UUID.
the URLs line concerned is:
path('user/detail/<uuid:pk>', UserDetailView.as_view(), name='userdetail'),
the template referring to it is:
<a href="{% url 'userdetail' user.pk %}">
which is generating the following URL:
http://127.0.0.1:8000/accounts/user/detail/809b0ec2-d604-4171-8966-0817bfd59c88
however I get:
Reverse for 'userdetail' with arguments '('',)' not found. 1 pattern(s) tried: ['accounts/user/detail/(?P[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$'].
If I use the username e.g. email from AbstractBase User, the detail view doesn't like it as it wants Pk or slug.
Help would be greatly appreciated.
EDIT: I am including the model below;
class UserDetails(AbstractBaseUser, PermissionsMixin):
FormFieldUserID = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
FormFieldTitle = models.CharField(max_length=75, help_text='Enter title',
verbose_name="Enter")
FormFieldFirstName = models.CharField(max_length=75, help_text='Enter First Name',
verbose_name="First Name") # Users First Name
FormFieldMiddleName = models.CharField(max_length=75, help_text='Enter Middle Name', blank=True,
verbose_name="Middle Names") # Users middle name
FormFieldLastName = models.CharField(max_length=75, help_text='Enter Last Name',
verbose_name="Last Name") # users last name
email = models.EmailField(max_length=254, unique=True, help_text="Enter Username/email",
verbose_name="Email Address") # user email
FormFieldUserImg = ResizedImageField(size=[40,40], crop=['middle', 'center'], upload_to='project/images/',
help_text="Choose project image", blank=True)
FormFieldAddr1 = models.CharField(max_length=100, help_text='Enter Address',
verbose_name="Address 1") # Users Address
FormFieldAddr2 = models.CharField(max_length=100, help_text='Enter Address', blank=True,
verbose_name="Address 2") # Users Address
FormFieldAddr3 = models.CharField(max_length=100, help_text='Enter Address', blank=True,
verbose_name="Address 3") # Users Address
FormFieldAddr4 = models.CharField(max_length=100, help_text='Enter Address', blank=True,
verbose_name="Address 4") # Users Address
FormFieldCounty = models.CharField(max_length=200, help_text='Enter County',
verbose_name="County") # Users county
FormFieldCountry = CountryField(help_text='Select user country', verbose_name="Country") # Users country
FormFieldAddrCode = models.CharField(max_length=20, help_text='Enter zip/post code',
verbose_name="Post Code") # Users Post Code
FormFieldMobileNo = models.CharField(max_length=25, help_text="Enter Mobile Phone Number",
verbose_name="Mobile Number") # User mobile Number
FormFieldPhoneNo = models.CharField(max_length=25, help_text="Enter Phone Number",
verbose_name="Phone Number",blank=True) # User phone Number
FormFieldWebAddr = models.CharField(max_length=254, help_text='Enter website details',
verbose_name="Website Details",blank=True) # User Website details
FormFieldUserNotes = models.CharField(max_length=254, help_text='Enter any user notes',
verbose_name="User Notes",blank=True) # User notes
FormFieldDateAdded = models.DateTimeField(default=datetime.now, help_text='Date user added',
verbose_name="User added date")
FormFieldAddedBy = models.CharField(default=settings.AUTH_USER_MODEL, max_length=200,
help_text='Select update detail', verbose_name="Used added by")
# Fields required by Abstract Model for users auth
is_active = models.BooleanField(default=True, help_text='Is User Active',
verbose_name="User Active") # Default must be true )
is_admin = models.BooleanField(default=False, help_text='Is user an administrator',
verbose_name="Admin User") # Default must be false)
USERNAME_FIELD = 'email'
objects = CustomUserManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
"""Does the user have a specific permission?"""
# Simplest possible answer: Yes, always
return True
def has_module_perms(self, app_label):
"""Does the user have permissions to view the app `app_label`?"""
# Simplest possible answer: Yes, always
return True
#property
def is_staff(self):
"""Is the user a member of staff?"""
# Simplest possible answer: All admins are staff
return self.is_admin
class Meta:
verbose_name = 'User Detail'
verbose_name_plural = 'User Details'

put this because your path it's nedd to pk (int or str ...)
<a href="{% url 'userdetail' pk=user.pk %}">
if don't work put this :
path('user/detail/<str:pk>', UserDetailView.as_view(), name='userdetail'),

Related

Update user profile with user uuid

I want to update user profile passing user uuid as kwarg.
Here is the url:
path("profile/update/<uuid:pk>", UpdateProfile.as_view(), name="update_profile"),
However, after I try to update my profile, it gives me an error.
Here is my view:
class UpdateProfile(LoginRequiredMixin, UpdateView):
model = Profile
user_type_fields = {
"Buyer": ["photo", "first_name", "last_name", "city"],
"Celler": ["photo", "name", "city", "address"],
}
def get(self, request, *args, **kwargs):
print(kwargs)
self.fields = self.user_type_fields[get_user_model().objects.get(pk=kwargs["pk"]).type]
return super().get(request, *args, **kwargs)
And here is the error itself:
Page not found (404)
No profile found matching the query
As I understand, django tries to find profile with uuid as in url, doesn't find it and returns me this error. However, if I change model in my view to user, it wouldn't be able to find fields as they belong to profile model. The only working option was to pass profile id as kwarg, but I don`t find it preferrable due to security reasons.
Could someone give me an advice on how to update profile with user uuid in kwargs?
Thanks in advance!
UPD:
Here are User and Profile models:
class CustomUser(AbstractBaseUser, PermissionsMixin):
class UserTypeChoices(models.TextChoices):
SINGLE_VOLUNTEER = "Single Volunteer", _("Single Volunteer")
VOLUNTEERS_ORGANISATION = "Volunteers Organisation", _("Volunteers Organisation")
CIVIL_PERSON = "Civil Person", _("Civil Person")
MILITARY_PERSON = "Military Person", _("Military Person")
type = models.CharField(
max_length=23,
choices=UserTypeChoices.choices,
)
uuid = models.UUIDField(
primary_key=True,
default=uuid4,
unique=True,
db_index=True,
editable=False,
)
email = models.EmailField(
_("email address"),
null=True,
blank=True,
)
phone = PhoneNumberField(
_("phone"),
null=True,
blank=True,
)
is_staff = models.BooleanField(
_("staff status"),
default=False,
help_text=_("Designates whether the user can log into this admin site."),
)
is_active = models.BooleanField(
_("active"),
default=True,
help_text=_(
"Designates whether this user should be treated as active. " "Unselect this instead of deleting accounts."
),
)
def __str__(self):
if self.email:
return str(self.email)
else:
return str(self.phone)
USERNAME_FIELD = "email"
objects = CustomUserManager()
class Profile(models.Model):
user = models.OneToOneField(to="accounts.CustomUser", on_delete=models.CASCADE, blank=True, null=True)
photo = models.ImageField(upload_to="profile/", blank=True, null=True, default="profile/profile_default.png")
name = models.CharField(_("name"), max_length=150, blank=True, null=True, default=None)
first_name = models.CharField(_("first name"), max_length=150, blank=True, null=True, default=None)
last_name = models.CharField(_("last name"), max_length=150, blank=True, null=True, default=None)
city = models.CharField(_("city"), max_length=150, blank=True, null=True, default=None)
address = PlainLocationField()
def __str__(self):
if self.user.email:
return str(self.user.email)
else:
return str(self.user.phone)
Assuming the following model, where a user only has one profile:
class Profile(models.Model):
user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE)
photo = models.ImageField()
# ... your other fields
You can then overwrite the get_object() method:
class UpdateProfile(LoginRequiredMixin, UpdateView):
model = Profile
fields = ['photo', '...']
def get_object(self):
user = get_user_model().objects.get(pk=self.kwargs['pk'])
profile = user.profile
return profile
And then use the UpdateView as normal.

Dynamic Choices (Those that get updated for new values entered.)

In this project, I got three types of users: ChalkSlateAdmin (this is not a superuser, administrator or staff, etc.), Student and Teacher. All of these can be considered ChalkSlateUser as each have a OneToOne Relationship with the model. ChalkSlateAdmin can be considered an institute and any time someone registers as a ChalkSlateAdmin, there is a new institute as ChalkSlateAdmin has that attribute.
Teachers and Students can join institutes (ChalkSlateAdmin attribute) that are already registered. So, I need to create a form that has choices of institutes that are currently registered.
My question is, how can I define choices that change depending on what institutes (ChalkSlateAdmin attribute) are registered? Before this, I used constant string values for choices like male & female.
models.py,
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.db import models
class MyAccountManager(BaseUserManager):
def create_user(self, username, email, password=None):
if not email:
raise ValueError("Users must have an email address.")
if not username:
raise ValueError("Users must have a username.")
user = self.model(
email=self.normalize_email(email),
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email, username, password):
user=self.create_user(
email=self.normalize_email(email),
password=password,
username=username,
)
user.user_type = 1
user.is_admin = True
user.is_staff = True
user.is_superuser = True
user.save(using=self._db)
class ChalkSlateUser(AbstractBaseUser):
# required to include
email = models.EmailField(verbose_name='email', unique=True, max_length=60)
username = models.CharField(max_length=60, unique=True)
date_joined = models.DateField(verbose_name='date joined', auto_now_add=True)
last_login = models.DateField(verbose_name='last login', auto_now=True)
is_admin = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
# new
first_name = models.CharField(max_length=60, verbose_name='first name')
last_name = models.CharField(max_length=60, verbose_name='last name')
has_institute = models.BooleanField(default=False)
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['username',]
objects = MyAccountManager()
def __str__(self):
return self.email
def has_perm(self, perm, obj=None):
return self.is_admin
def has_module_perms(self, app_label):
return True
AUTHORITY = 1
INSTITUTE = 2
STUDENT = 3
TUTOR = 4
USER_TYPE_CHOICES = (
(AUTHORITY, 'Authority (superuser or admin)'),
(INSTITUTE, 'ChalkSlateAdmin'),
(STUDENT, 'Student'),
(TUTOR, 'Tutor'),
)
user_type = models.PositiveSmallIntegerField(choices=USER_TYPE_CHOICES, null=True, blank=True)
# user_type = models.PositiveSmallIntegerField(null=True, blank=True)
# is_admin = models.BooleanField(default=False)
# is_student = models.BooleanField(default=False)
# is_tutor = models.BooleanField(default=False)
class ChalkSlateAdmin(models.Model):
chalkslate_user = models.OneToOneField(ChalkSlateUser, on_delete=models.CASCADE, null=True)
# username_institute = models.CharField(max_length=100, unique=True)
institute_name = models.CharField(verbose_name='institute name', max_length=100, unique=True)
institute_details = models.CharField(verbose_name='institute details', max_length=100)
def __str__(self):
return self.chalkslate_user.email
class Student(models.Model):
chalkslate_user = models.OneToOneField(ChalkSlateUser, on_delete=models.CASCADE)
# username_student = models.CharField(max_length=100, unique=True)
# name = models.CharField(max_length=100)
student_details = models.CharField(verbose_name='student details', max_length=100)
picture = models.ImageField(verbose_name='picture', upload_to='student_pictures')
def __str__(self):
return self.chalkslate_user.email
class Tutor(models.Model):
chalkslate_user = models.OneToOneField(ChalkSlateUser, on_delete=models.CASCADE)
# username_tutor = models.CharField(max_length=100, unique=True)
# name = models.CharField(max_length=100)
tutor_details = models.CharField(verbose_name='tutor details', max_length=100)
picture = models.ImageField(verbose_name='picture', upload_to='tutor_pictures')
def __str__(self):
return self.chalkslate_user.email
# make the ins_tutor and ins_student models
class InsStudent(models.Model):
institute = models.ForeignKey(ChalkSlateAdmin, on_delete=models.CASCADE)
student = models.OneToOneField(Student, on_delete=models.CASCADE)
roll = models.IntegerField()
class_year = models.CharField(max_length=50)
section = models.CharField(max_length=50)
class Meta:
unique_together = ('roll', 'class_year', 'section',)
class InsTutor(models.Model):
institute = models.ForeignKey(ChalkSlateAdmin, on_delete=models.CASCADE)
tutor = models.OneToOneField(Tutor, on_delete=models.CASCADE)
class notice(models.Model):
name=models.CharField(max_length=50,null=False)
mail=models.CharField(max_length=50,null=False)
date=models.DateTimeField(null=False)
content=models.CharField(max_length=200,null=False)
per=models.CharField(max_length=50,default='no')
def __str__(self):
return self.name
For choices option, you can set a method that returns a list with what you want in it.
For instance, for a BankCard model I implemented in one of my projects, I did something similar to what you want to achieve, for the expiration_year. See below :
class BankCard(models.Model):
def _years(year):
return [(year, str(year)) for year in range(year, year + 10)]
expiration_year = models.IntegerField(choices=_years(datetime.datetime.now().year))
Maybe you could do something similar.

ValueError at /user/register Cannot assign "('Civil Engineering (CE)',)": "User.department" must be a "Department" instance

I cannot insert data into a database.
I want to create a user with specific department name and the department table, with a foreign key to detect the user from a certain department.
Here is my model file:
class Department(models.Model):
name = models.CharField(max_length=100, blank=False, null=False)
admin_id = models.ForeignKey('Admin' , on_delete=models.CASCADE)
admin_post_id = models.ForeignKey('Admin_Post' , on_delete=models.CASCADE)
def __str__(self):
return name
This is my custom user model:
class User(AbstractBaseUser):
first_name = models.CharField(max_length=50, blank=False, null=False)
last_name = models.CharField(max_length=50, blank=False, null=False)
address = models.CharField(max_length=150)
phone_number = models.IntegerField( blank=False, null=False, unique=True)
department = models.ForeignKey('Department' , on_delete=models.CASCADE)
semester = models.FloatField(blank=False, null=False)
registation = models.IntegerField(blank=False, null=False, unique=True)
email = models.EmailField(max_length=150, blank=False, null=False, unique=True)
password = models.CharField(max_length=150, blank=False)
password_con = models.CharField(max_length=150, blank=False, null=True)
USERNAME_FIELD = 'email'
REQUIRED_FIELD = ['email']
objects = UserManager()
def _str__(self):
return registration;
Here is my view file:
def register(request):
if request.method == 'POST':
first_name = request.POST['first_name']
last_name = request.POST['last_name']
address = request.POST['address']
phone_number = request.POST['phone_number']
department = request.POST['department']
semester = request.POST['semester']
registration = request.POST['registration']
email = request.POST['email']
password = request.POST['password']
password_con = request.POST['password_con']
user = Department()
user = User.objects.create_user(first_name=first_name ,last_name=last_name ,address=address ,phone_number=phone_number ,department=department ,semester=semester ,registration=registration ,email=email ,password=password)
if User.objects.filter(email=email).exists():
messages.info(request,'Email is Already taken')
elif User.objects.filter(registration=registration):
messages.info(request,'Registration Id is Already taken')
elif password != password_con:
messages.info(request,'Credentials not mathcing')
else:
# user.department = Department.objects.get()
user.save()
print('user created')
return redirect('signin/')
else:
return render(request,'register.html')
you are trying to make a database relation out from a name, you can't do that in Django.
You must first retrieve the Department instance that correponds to the POST data and the give it so that Django creates a foreign key relation.
Something like this
# retrieve object
department_instance = Department.objects.get(name=request.POST['department']) # here 'Civil Engineering (CE)'
# use the instance (actually only the ID of that instance will be stored in the table User, but that's a detail)
User.objects.create_user(department=department_instance.id, etc...) #you can omit '.id'
Your line
department = request.POST['department']
should be something like:
department = Department.objects.get(id=request.POST['department'])

form object has no attribute 'email' in django

I have a registration form made of 2 forms, from which email field gets saved in both User and Student models. Now, I made an update account info view. Problem is, I want that email will get updated the in both models. But I get error:
'StudentEditForm' object has no attribute 'email'
Here is my code:
class StudentEditForm(forms.ModelForm):
email = forms.EmailField(required=False)
name = forms.CharField(max_length=30)
surname = forms.CharField(max_length=50)
photo = forms.ImageField(required=False)
phone = forms.CharField(max_length=15, required=False)
class Meta:
model = Student
fields = ('email', 'name', 'surname', 'phone', 'photo')
class User(AbstractUser):
pass
class Student(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, primary_key=True)
name = models.CharField(max_length=30, null=True, blank=True, default=None)
surname = models.CharField(max_length=50, null=True, blank=True, default=None)
email = models.EmailField(unique=True, null=True, blank=True, default=None)
student_ID = models.CharField(unique=True, max_length=14,
validators=[RegexValidator(regex='^.{14}$',
message='The ID needs to be 14 characters long.')],
null=True, blank=True, default=None)
photo = models.ImageField(upload_to='students_images', null=True, blank=True, default=None)
phone = models.CharField(max_length=15, null=True, blank=True, default=None)
def __str__(self):
return self.surname
User.student = property(lambda p: Student.objects.get_or_create(user=p)[0])
def profile_edit(request):
user = request.user
student = request.user.student
if request.method != 'POST':
form = StudentEditForm(instance=student)
else:
form = StudentEditForm(request.POST, instance=student)
user.email = form.email
form.save()
return render(request, 'index.html')
context = {
"form": form,
}
return render(request, "registration/profile_edit.html", context)
Again, I need that I will be able to update the email fields. And the email will get saved in User email but also I want it saved to Student email.
call form.is_valid() and then use form.cleaned_data['email'], see https://docs.djangoproject.com/en/1.11/topics/forms/
I had to add
form.is_valid()
and
user.email = form.cleaned_data['email']
but also to add user.save() which solved this issue.

Get email in another model after user is created in django

I am a beginner in django. When admin creates a user, I am trying to save some fields in EmailAddress model.But for some reason the email field is always blank. Is there any way I can update the instance with email in UserProfile or EmailAddress model.
models.py looks like this
User._meta.get_field('email').blank = False
User._meta.get_field('email')._unique = True
class EmailAddress(models.Model):
user = models.OneToOneField(User, unique=True, related_name ='address')
email = models.EmailField()
verified = models.BooleanField(verbose_name=_('verified'), default=True)
primary = models.BooleanField(verbose_name=_('primary'), default=True)
class Meta:
db_table = 'account_emailaddress'
class UserProfile(models.Model, HashedPk):
user = models.OneToOneField(User, unique=True, related_name ='profile')
job_title = models.CharField(max_length=128, blank=True, null=False, default="")
website = models.URLField(max_length=255, blank=True, null=True)
organisation = models.CharField(max_length=50, blank=True, null=True, default="")
phone_number = PhoneNumberField( blank=True, null=True)
#receiver(post_save, sender=User)
def create_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
EmailAddress.objects.create(user=instance)
forms.py looks like this --
class SignUpForm(forms.Form):
first_name = forms.CharField(max_length=30)
last_name = forms.CharField(max_length=30)
phone_number = PhoneNumberField(label=_("Phone (Please state your country code eg. +44)"))
organisation = forms.CharField(max_length=50)
email = forms.EmailField()
password1 = forms.CharField(max_length=20)
password2 = forms.CharField(max_length=20)
captcha = ReCaptchaField(attrs={'theme' : 'clean'})
def signup(self, request, user):
user.first_name = self.cleaned_data['first_name']
user.last_name = self.cleaned_data['last_name']
up = user.profile
up.phone_number = self.cleaned_data['phone_number']
up.organisation = self.cleaned_data['organisation']
user.save()
up.save()
Any help is highly appreciated.
Sorted. It needs to be
EmailAddress.objects.create(user=instance, email=instance.email)

Categories