I want to allow a user to edit a project page if ifAdmin (an object in uProject model) == True. I am currently trying to use #user_passes_test to render a view to update the project, but am having difficulties. I am getting uProjects from main.models, and I am working in projects.views. Here's my code.
def admin_check(uProjects):
return uProjects.ifAdmin = True
#user_passes_test(admin_check)
def update(request): etc, etc, etc
models.py
class uProjects(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
project = models.ForeignKey(Project, on_delete=models.CASCADE)
ifAccepted = models.BooleanField(null = True, blank=False, default=False)
#ifLeader = models.BooleanField(null = False, blank=False)
ifAdmin = models.BooleanField(null = True, blank=False, default=False)
title = models.CharField(max_length=100, null=False, blank=False)
def __str__(self):
return self.user.username + ',' + self.project.name
The difficulty is I'm trying to have admin_check work with uProjects, not the User model. I'm also trying to see if ifAdmin == True, but the way I did above renders an error. The error is that the "User object has no attribute ifAdmin"
You can use something like this:
def admin_check(user):
return user.uprojects_set.filter(ifAdmin=True).exists()
#user_passes_test(admin_check)
def update(request): etc, etc, etc
But this will work for any user which has ifAdmin permission in atleast one uProject instance. It can't distinguish by uProject information.
To do that, you can write a custom dectorator like this:
from functools import wraps
from django.http import HttpResponseRedirect
def admin_check(function):
#wraps(function)
def wrap(request, *args, **kwargs):
user = request.user
name = kwargs.get('name') # assuming you are getting the project id here via url: "/<project_id:int>"
if uProjects.objects.filter(title=name, user=user, ifAdmin=True).exists():
return function(request, *args, **kwargs)
else:
return HttpResponseRedirect('/')
return wrap
Related
I want to validate if my lesson material belongs to a xyz user with pro right it will show the correct conent, but if not it will display become a member , but however I am getting if I change id membership to pro or vice versa it always true the statement
def get(self, request):
template = loader.get_template(self.template_name)
template_member = loader.get_template(self.template_payment)
#rendering the template in HttpResponse
lesson = Lesson.objects.first()
user_membership = UserMembership.objects.filter(user=self.request.user).first()
user_membership_type = user_membership.membership.membership_type
lesson_allowed_mem_types = lesson.allowed_memberships.all()
if lesson_allowed_mem_types.filter(membership_type=user_membership_type).exists():
return HttpResponse(template.render())
else:
return HttpResponse(template_member.render())
models
class Lesson(models.Model):
allowed_memberships = models.ManyToManyField(Membership)
class Membership(models.Model):
membership_type = models.CharField(
choices=MEMBERSHIP_CHOICES,
default='Free',
max_length=30)
def __str__(self):
return self.membership_type
class UserMembership(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
membership = models.ForeignKey(Membership, on_delete=models.SET_NULL, null=True)
def __str__(self):
return self.user.email
Aren't you just trying to see if the user has a Membership?
if UserMembership.objects.filter(
user=request.user,
membership__membership_type="PAID MEMBER",
).exists():
# user is member
return HttpResponse(template.render())
else:
# user is not a member
return HttpResponse(template_member.render())
I'm pretty new to Django and I am working on a project that currently requires the following:
I have two basic structures: a Project model and a TeamMember model- both related to each other through a ManytoMany relationship. Then I have an TMAssigned 'through' class. The team member will have many projects assigned to it over time.
I have a ModelFrom which creates a Project model through the creation of the form.
My question is, How do I link the team member to the newly created project upon the submission of the form?
Here is a bit of my model & form code:
TeamMember
class TeamMember(models.Model):
firstname = models.CharField(max_length=100, default= "First Name")
lastname = models.CharField(max_length=100, default= "Last Name")
fullname = models.CharField(max_length=100, default= "Full Name")
email = models.EmailField(max_length=254)
cellphone = PhoneNumberField(null=False, blank=False, unique=True)
numberofcases = models.IntegerField(max_length=10000, default=0)
#property
def fullnamefunc(self):
fullname = "{} {}".format(self.firstname, self.lastname)
return fullname
def __str__(self):
return self.fullname
Project
class Project(models.Model):
pursuitname = models.CharField(max_length=500)
datecreated = models.DateTimeField(auto_now=True)
bdmember = models.ManyToManyField('team.TeamMember')
Views.py
class bdFormView(TemplateView):
template_name = os.path.join(BASE_DIR, "templates/masterform/bdform.html")
def get(self,request):
form = bdForm()
return render (request, self.template_name, {'form': form})
def post(self, request):
form = bdForm(request.POST)
if form.is_valid():
print("form is valid")
project = form.save(commit=False)
project.save()
text = form.cleaned_data['briefcard']
Form.py
class bdForm(forms.ModelForm):
bdmemberlist = TeamMember.objects.all().order_by('lastname')
pursuitname = forms.CharField()
bdmember = forms.ModelChoiceField(queryset= bdmemberlist)
addbdteam = forms.ModelMultipleChoiceField(
queryset=TeamMember.objects.all().order_by('lastname'), widget=Select2MultipleWidget, required=False)
class Meta:
model = Project
fields = ['pursuitname','addbdteam','bdmember',]
def __init__(self, *args, **kwargs):
if kwargs.get('instance'):
initial = kwargs.setdefault('initial', {})
initial['projects'] = [t.pk for t in
kwargs['instance'].project_set.all()]
forms.ModelForm.__init__(self, *args, **kwargs)
def save(self, commit=True):
instance = forms.ModelForm.save(self, False)
old_save_m2m = self.save_m2m
def save_m2m():
old_save_m2m()
for project in self.cleaned_data['bdmember']:
instance.teammember_set.add(project)
Thanks in advance!!
Edit- after doing some more research, I've removed the "Through" model from the script and am trying to rely on the form.py save method to do the join. However, when I do this- the two are still not linking up properly.
Since only your admin (superusers?) will log in, you can start off by using the in-built Django Admin.
I would recommend this for you, at least for now, because you're a beginner and the Admin Form is stunningly simple to use. Then, you can create a custom form later on when you're more comfortable. :-)
With this in mind, you can try eliminating the 'through' table (you may need to reset your migrations), and try this.
Admin.py
from django.contrib import admin
from .models import TeamMember, TMAssigned, Project,
TeamMembersInLine(admin.TabularInline):
model = TeamMember
extra = 1
#admin.register(Project):
class ProjectAdmin(admin.ModelAdmin):
list_display = ('pursuitname', 'bdmember ', 'datecreated')
inlines = [TeamMembersInLine]
Here's another answer that delves into the through table. It was asked by someone in your situation and the answer is relevant too.
I created a django form (IssueForm) which is meant to be used to register an object which is instance of one of my models (Issue). Following are the model:
model.py
class Issue(models.Model):
TYPE_FIELDS = [
("Math", "Math"),
("Physics", "Physics"),
("Programming", "Programming"),
("Arts", "Arts")
]
issue_text = models.TextField(default="Please insert text")
issue_description = models.TextField(default="Newly created")
issue_deadline = models.DateField()
issue_field = models.CharField(max_length=30, choices=TYPE_FIELDS)
published_by = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
def __str__(self):
return self.issue_description
the form used:
forms.py
class IssueForm(forms.ModelForm):
def __init__(self, user, *args, **kwargs):
self.user = user
super(IssueForm, self).__init__(*args, **kwargs)
TYPE_FIELDS = [
("Math", "Math"),
("Physics", "Physics"),
("Programming", "Programming"),
("Arts", "Arts")
]
issue_text = forms.CharField(widget=forms.Textarea, required=True)
issue_description = forms.CharField(widget=forms.Textarea, required=True)
issue_deadline = forms.DateField(required=True)
issue_fields = forms.ChoiceField(choices=TYPE_FIELDS, required=True)
class Meta:
model = Issue
fields = [
'issue_text',
'issue_description',
'issue_deadline',
'issue_fields'
]
def save(self, commit=True):
issue = super(IssueForm, self).save(commit=False)
issue.issue_text = self.cleaned_data['issue_text']
issue.issue_description = self.cleaned_data['issue_description']
issue.issue_deadline = self.cleaned_data['issue_deadline']
issue.issue_fields = self.cleaned_data['issue_fields']
if commit:
issue.published_by = self.user
issue.save()
return issue
and the related view:
views.py
def create_issue(request):
if ExtendedUser.objects.filter(user=request.user).exists():
if request.method == 'POST':
form = IssueForm(request.user, request.POST)
if form.is_valid():
form.save()
return redirect("/issues")
else:
form = IssueForm(request.user)
args = {'form': form}
return render(request, "issues/create_issue.html", args)
else:
raise Http404("You are not allowed to perform this action")
The forms works for every field in the model, they are all registered right, except for issue_fields. If i try giving a default value to the field in the model, that is the value that is saved on the database, otherwise I just get an empty field. Also I believe the problem comes from the form used, because if i try to create a new issue from the django admin interface it works just fine.
I feel like it's one of those silly mistakes, but I'm just starting with django and python in general and cannot figure it out on my own.
Thank you for your time!!
The field on your model is called issue_field, but you set issue_fields.
Note that also you are doing far more work here than necessary. Your save method completely duplicates what the superclass does already; you should remove all that code except for the setting of the user value.
enter code hereIf you want to use Choices, you haven't to write one more time list of choices in your forms.py file.
This is an example :
#In your models.py file
LIST_CHOICE = (('A','A'), ('B','B'))
class Test(models.Model) :
foo = models.CharField(choices=LIST_CHOICE, verbose_name="foo")
and
#In your form.py file
TestForm(forms.Modelform) :
class Meta :
model = Test
fields = ['foo']
It's not necessary to overwrite LIST_CHOICE in your form file ;)
So, dont touch to your model.py file, but in your form.py file, just write :
class IssueForm(forms.ModelForm):
issue_text = forms.CharField(widget=forms.Textarea)
issue_description = forms.CharField(widget=forms.Textarea)
def __init__(self, user, *args, **kwargs):
self.user = user
super(IssueForm, self).__init__(*args, **kwargs)
class Meta:
model = Issue
fields = [
'issue_text',
'issue_description',
'issue_deadline',
'issue_fields'
]
Don't forget to remove s in issue_field ;)
So i have this two models in django:
class Course(models.Model):
def get_image_path(self, filename):
return os.path.join('courses', str(self.slug), filename)
def __str__(self):
return self.name
def save(self, *args, **kwargs):
self.slug = slugify(self.name)
super(Course, self).save(*args, **kwargs)
name = models.CharField(max_length=255, verbose_name="Nombre")
description = models.CharField(max_length=255, verbose_name="DescripciĆ³n")
price = models.DecimalField(max_digits=12,decimal_places=2, verbose_name="Precio")
slug = models.SlugField(blank=True, max_length=255)
icon_img = models.ImageField(upload_to=get_image_path, blank=True, null=True, verbose_name="Imagen")
background_color = ColorField(default="#026085")
class Meta:
verbose_name = "curso"
verbose_name_plural = "cursos"
class UserCourse(models.Model):
user = models.ForeignKey(User)
course = models.ForeignKey(Course)
So whenever a user "buys" a course, it is stored in UserCourse. I have a view where the system shows a list of all the courses the user has bought. This is the view code:
def user_course_list_view(request, username):
context_dict = {}
try:
user_courses = UserCourse.objects.filter(user=request.user).course_set
context_dict['courses'] = user_courses
context_dict['heading'] = "Mis cursos"
except:
context_dict['courses'] = None
context_dict['heading'] = "Mis cursos wey"
return render(request, 'courses/course_list.html', context=context_dict)
I dont know where is the error and I cant seem to catch the exception (im using django with docker)
tl;dr
Something like this should work.
usercourse_objects = UserCourse.objects.filter(user=request.user).select_related('course')
user_courses = [x.course for x in usercourse_objects]
Explanation
There are multiple ways to do this, but one way would be to first get all the UserCourse objects for the current user:
usercourse_objects = UserCourse.objects.filter(user=request.user)
Then, for each UserCourse object, get the related Course:
user_courses = [x.course for x in usercourse_objects]
Now, the second line causes N database queries (one for each time we follow the course foreign key relation. To prevent this, the first line can be changed to:
usercourse_objects = UserCourse.objects.filter(user=request.user).select_related('course')
This pre-populates the course attribute of the UserCourse objects. More info about select_related() can be found here.
I am trying to log the activities during save operation to track all the changes to user model. my approach is as follows.
class User(AbstractUser):
undergrad_college = models.CharField(max_length=20, choices=COLLEGE_CHOICES)
undergrad_degree = models.CharField(max_length=20, choices=COLLEGE_DEGREES)
postgrad_college = models.CharField(max_length=20, choices=COLLEGE_CHOICES)
postgrad_degree = models.CharField(max_length=20, choices=COLLEGE_DEGREES)
currently_working_on = models.TextField()
previous_work_experience = models.TextField()
previous_internship_experience = models.TextField()
def __str__(self):
return self.username
def save(self, *args, **kwargs):
Log(user=User, actions="Updated profile",
extra={"undergrad_college": self.undergrad_college,
"undergrad_degree": self.undergrad_degree,
"postgrad_college": self.postgrad_college,
"postgrad_degree": self.postgrad_degree,
"currently_working_on": self.currently_working_on,
"previous_work_experience": self.previous_work_experience,
"previous_internship_experience": self.previous_internship_experience
})
super(User, self).save(args, **kwargs)
my views are like this for handling the logging.
class ActivityMixin(LoginRequiredMixin):
def get_context_data(self, **kwargs):
context = super(ActivityMixin, self).get_context_data(**kwargs)
context['activities'] = Log.objects.filter(user=self.request.user)
return context
class IndexListView(ActivityMixin, ListView):
template_name = 'pages/home.html'
model = User
I get this error while performing the update action.
Cannot assign "<class 'users.models.User'>": "Log.user" must be a "User" instance.
Update view is as follows
class UserUpdateView(LoginRequiredMixin, UpdateView):
form_class = UserForm
# we already imported User in the view code above, remember?
model = User
# send the user back to their own page after a successful update
def get_success_url(self):
return reverse("users:detail",
kwargs={"username": self.request.user.username})
def get_object(self, **kwargs):
# Only get the User record for the user making the request
return User.objects.get(username=self.request.user.username)
How to assign the User model instance to the Log function. I cant get this working. I am Django newbie.
Looks like pretty straightforward, replace User with self:
Log(user=User, ...
Log(user=self, ...