I used a class based view to update a user profile using this code
class EditProfileViewClass(generic.UpdateView):
model = UserProfile
fields = ['bio', 'profile pic']
template_name = 'users/update.html'
success_url = reverse_lazy('home')
path('profile/<int:pk>/update', EditProfileViewClass.as_view(), name="profile"),
Your Profile
the issue right now is, Instead of having the url like the one above, I want it to be like
path('profile/<str:username>/update', EditProfileViewClass.as_view(), name="profile"),
but unfortunately I get an attribute error saying:
Generic detail view EditProfileView must be called with either an object pk or a slug in the URLconf.
So I tried making a function based view so I can get the "username" from the url, doing that didn't allow me to get the form I needed to update the specific username.
Any help would be great. Thanks.
In your EditProfileViewClass view you can add pk_url_kwarg or slug_url_kwarg.
class EditProfileViewClass(UpdateView):
model = UserProfile
fields = ['bio', 'profile pic']
template_name = 'users/update.html'
success_url = reverse_lazy('home')
pk_url_kwarg = 'username'
slug_url_kwarg = 'username'
You can use a class-based view, you only need to update the the slug_field (which determines on what should be used), and the slug_url_kwargs:
class EditProfileViewClass(UpdateView):
model = UserProfile
fields = ['bio', 'profile_pic']
template_name = 'users/update.html'
success_url = reverse_lazy('home')
slug_field = 'user__username'
slug_url_kwarg = 'username'
This will thus take the username parameter of the URL, and it will filter the queryset to only retrieve a UserProfile that is linked to a user with that username.
Related
I`m trying to make a CreateView form that takes the UID of the object as a foreign key from the previous page.
Here I got DetailView of Plan model:
class PlanDetailView(IsStaffPermissionMixin, DetailView):
model = Plan
template_name = "backoffice/plans/plan_detail.html"
context_object_name = 'plan'
def get_object(self):
uid = self.kwargs.get("uid")
return get_object_or_404(Plan, uid=uid)
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super().get_context_data(**kwargs)
practice_sessions = PracticeSession.objects.all().filter(plan__uid=self.kwargs.get("uid"))
context['practice_sessions'] = practice_sessions
return context
And here I got a PracticeSession CreateView:
class PracticeSessionCreateView(IsStaffPermissionMixin, CreateView):
model = PracticeSession
template_name = "backoffice/practice_session/practice_session_create.html"
fields = ['uid', 'title', 'plan', 'snippet', 'welcome_content', 'done_content', 'order_index', ]
success_url = reverse_lazy('practice-sessions')
As you understand, PracticalSession contains Foreign Key for the Plan model
Now I want that when I click on the button to create a PracticalSession (the picture below), I create a form in which the plan field already contains a "uid" of Plan from the page of which I create a new PracticalSession
My Form:
class PracticeSessionCreateForm(ModelForm):
class Meta:
model = PracticeSession
fields = '__all__'
Big THANK YOU In advance !!!
I am trying to check if the user id not equal to 1 then he should not be able to update few fields. I tried something similar to the following code but it did not work because of the following issues
self.user.id don't actually return the user I need to get the authenticated user in different why?
the def function maybe should have a different name like update?
also the general way maybe wrong?
class ForAdmins(serializers.ModelSerializer)):
class Meta:
model = User
fields = '__all__'
class ForUsers(serializers.ModelSerializer)):
class Meta:
read_only_fields = ['email','is_role_veryfied','is_email_veryfied']
model = User
fields = '__all__'
class UsersSerializer(QueryFieldsMixin, serializers.ModelSerializer):
def customize_read_only(self, instance, validated_data):
if (self.user.id==1):
return ForAdmins
else:
return ForUsers
class Meta:
# read_only_fields = ['username']
model = User
fields = '__all__'
You can make the decision which serializer you want to pass from your views
or
you can do it inside modelSerializer update method.
for getting user from Serializer class Try:
request = self.context.get('request', None)
if request:
user = request.user
for getting user from View class Try:
user = self.request.user
I have two groups 'user' and 'moderator' with no specific permissions added (Chosen permissions empty).
I have also three views to add/edit/delete objects, user can only add whereas moderator can edit/delete
views.py
class AddView(GroupRequiredMixin, CreateView):
model = Post
form_class = UpdateForm
template_name = 'post_add.html'
group_required = u"user"
class UpdateView(GroupRequiredMixin, UpdateView):
model = Post
form_class = UpdateForm
template_name = 'post_update.html'
group_required = u"moderator"
class DeleteView(GroupRequiredMixin, DeleteView):
model = Post
template_name = 'post_delete.html'
group_required = u"moderator"
The question is do i need to add permissions to the groups or it is the same thing if I leave the groups empty?
for exmple add a permission to group 'user' that he can only add objects to model post ? or it is not needed ? thanks
How to populate a form from DB based on the pk? So if the url is http://demo.com/edit-voucher/123456, how do I get the values of voucher entry 123456 into the form?
The form displays, but don't know how to populate it...
urls.py:
url(r'^edit-voucher/(?P<pk>[\d]+)', reports.EditVoucherView.as_view()),
forms.py:
class EditVoucherForm(forms.ModelForm):
class Meta:
model = Vouchers
fields = ['event_name', 'valid_start', 'valid_end', 'duration']
views.py:
class EditVoucherView(LoginRequiredMixin, GroupRequiredMixin, FormView):
template_name = 'edit_voucher.html'
group_required = u'voucherEdit'
form_class = EditVoucherForm
You can use UpdateView instead of FormView:
class EditVoucherView(LoginRequiredMixin, GroupRequiredMixin, UpdateView):
template_name = 'edit_voucher.html'
group_required = u'voucherEdit'
form_class = EditVoucherForm
model = Vouchers
It looks like you can access the pk of the form in your template as it is in the url. If you use pycharm, try using the debugger to see if the pk value is available in the template.
I have recently installed autocomplete-light in my app.
Autocomplete filters through the field called 'name' in a table called institution. However, what is post through the view is the 'id' of the same object, not the name.
Does anyone know why that is?
My view is:
class UserAccountsUpdate(UpdateView):
context_object_name = 'variable_used_in `add_user_accounts.html`'
form_class = AddUserAccountsForm
template_name = 'add_user_accounts.html'
success_url = 'add_user_accounts.html'
def add_user_institution_details(request):
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = AddUserAccountsForm(request.POST)
# check whether it's valid:
if form.is_valid():
institution_selected = Institution.objects.get(id=name)
form.save()
return render(request)
#get object
def get_object(self, queryset=None):
return self.request.user
The form is:
class AddUserAccountsForm(forms.ModelForm):
name = forms.ModelChoiceField(required=True, queryset=Institution.objects.all(), widget=autocomplete_light.ChoiceWidget('InstitutionAutocomplete'), label="")
class Meta:
model = Institution
fields = ('name',)
autocomplete-light's ChoiceWidget uses the Model's PrimaryKey for post requests by default, which in your case is id.
Since you did not post your models.py I can only assume that name is a CharField in the Institution model and you are just using autocomplete here to simplify the adding of a name.
To realize this use TextWidget and forms.CharField:
class AddUserAccountsForm(forms.ModelForm):
name = forms.CharField(
required=True,
widget=autocomplete_light.TextWidget('InstitutionAutocomplete'),
label="",
)
class Meta:
model = Institution
fields = ('name',)