I created an update screen for django. However, although it redirects to successURL, the data has not been updated. I don't know why.
I need your help.
I will post it if necessary.
#view
class RecordDetailEdit(UpdateView,LoginRequiredMixin):
template_name = 'records/detail_edit.html'
model = URC
form_class = RecordDetailEditForm
pk_url_kwarg = 'id'
success_url = reverse_lazy('person:home')
def get_object(self):
return get_object_or_404(User, pk=self.request.user.user_id)
def get_form_kwargs(self):
kwargs = super(RecordDetailEdit, self).get_form_kwargs()
# get users, note: you can access request using: self.request
kwargs['user'] = self.request.user
return kwargs
#form
class RecordDetailEditForm(forms.ModelForm):
class Meta:
model = URC
fields = ('UPRC','URN','UET','URT')
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(RecordDetailEditForm, self).__init__(*args, **kwargs)
self.fields['URN'].queryset = UPRM.objects.filter(user=user)
#model
class URC(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
UPRC = models.CharField(max_length=300)
URN = models.ForeignKey(UPRM, on_delete=models.CASCADE)
UET = models.DurationField(editable=True)
URT = models.DateTimeField(default=timezone.now,editable=True)
group = models.ForeignKey(group, on_delete=models.CASCADE, null=True)
def __str__(self):
return self.UPRC
#url
path('<id>/edit/', views.RecordDetailEdit.as_view(), name='record_detail_edit'),
I changed it to the following.
def get_object(self, queryset=None):
obj = URC.objects.get(id=self.kwargs['id'])
return obj
Related
class Post(models.Model):
cat_post = models.ForeignKey(Category, on_delete=models.CASCADE, blank=True,null=True)
top_post = models.ForeignKey(TopicsCategory, on_delete=models.CASCADE, blank=True,null=True)
sub_post = models.ForeignKey(SubTopicsCategory, on_delete=models.CASCADE, blank=True,null=True)
class CreatePostView(CreateView):
model = Post
template_name = 'blog/create.html'
form_class = CreatePostForm
def get_context_data(self, *args, **kwards):
print(self.kwargs)
context = super(CreatePostView, self).get_context_data(**kwards)
context['btn'] = 'Add'
return context
def form_valid(self, form, *args, **kwargs):
if self.kwargs.get('category_slug') and len(self.kwargs) == 1:
category = Category.objects.get(slug=self.kwargs['category_slug'])
form.instance.cat_post = category
return super(CreatePostView, self).form_valid(form)
# передача в форму kwargs view
def get_form_kwargs(self):
kwargs = super(CreatePostView, self).get_form_kwargs()
kwargs.update({'view_kwargs': self.kwargs})
return kwargs
def get_success_url(self):
return reverse('topics_category_list', kwargs={'category_slug': self.kwargs['category_slug'], })
class CreatePostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['name', 'text', 'discussion']
# widgets = {
# 'cat_post': forms.HiddenInput(),
# }
def __init__(self, *args, **kwargs):
self.request = kwargs.pop("view_kwargs")
super(CreatePostForm, self).__init__(*args, **kwargs)
def clean_name(self):
name = self.cleaned_data['name']
if self.request.get('category_slug') and len(self.request) == 1:
category = Category.objects.get(slug=self.request['category_slug'])
unique = Post.objects.filter(slug=slugify(self.cleaned_data['name']), cat_post=category.pk,discussion=False).exists()
if unique:
raise ValidationError(f'Post is not unique')
return name
**
I have duplicate sources in db here form_valid and clean_name.
How do I pass the form in the view form form_valid class instance that I got from the database to clean_name.
There will be posts for 2 models and requests will increase
Although it is in the title, I want to change the form dynamically with django.
But now I get an error.
I can't deal with it.
I was able to get user information, but if I filter it, it will be “cannot unpack non-iterable UPRM object”.
#forms.py
class RecordCreateForm(BaseModelForm):
class Meta:
model = URC
fields = ('UPRC','URN','UET','URT',)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(RecordCreateForm,self).__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
self.fields['URN'].choices = UPRM.objects.filter(user=user)
#views.py
class RecordCreate(CreateView):
model = URC
form_class = RecordCreateForm
template_name = 'records/urcform.html'
success_url = reverse_lazy('person:home')
def get_form_kwargs(self):
kwargs = super(RecordCreate, self).get_form_kwargs()
# get users, note: you can access request using: self.request
kwargs['user'] = self.request.user
return kwargs
#models
class UPRM(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
URN = models.CharField( max_length=30,editable=True)
def __str__(self):
return self.URN
class URC(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
UPRC = models.CharField(max_length=300)
URN = models.ForeignKey(UPRM, on_delete=models.CASCADE)
def __str__(self):
return self.UPRC
cannot unpack non-iterable UPRM object
You should use queryset instead of choices here:
class RecordCreateForm(BaseModelForm):
class Meta:
model = URC
fields = ('UPRC','URN','UET','URT',)
def __init__(self, *args, **kwargs):
user = kwargs.pop('user')
super(RecordCreateForm,self).__init__(*args, **kwargs)
for field in self.fields.values():
field.widget.attrs['class'] = 'form-control'
self.fields['URN'].queryset = UPRM.objects.filter(user=user)
I have a problem with the form in django. It uses the CheckboxSelectMultiple widget, but I need to set a list of possible choices only for posts created by the currently logged in user.
Any idea?
form:
class CycleForm(BSModalForm):
class Meta:
model = Cycle
fields = ['title', 'description', 'posts']
widgets = {
'posts': forms.CheckboxSelectMultiple(),
}
models
class Cycle(models.Model):
title = models.CharField(max_length=200, unique=True)
description = models.TextField(max_length=500, default="Brak opisu")
date_created = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
posts = models.ManyToManyField(Post)
def __str__(self):
return self.title
class Post(models.Model):
title = models.CharField(max_length=50, unique=True)
content = MDTextField()
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
numbers_of_entries = models.IntegerField(default=0)
views
class CycleCreateView(BSModalCreateView, LoginRequiredMixin):
template_name = 'blog/cycle_form.html'
form_class = CycleForm
def form_valid(self, form, **kwargs):
form.instance.author = self.request.user
return super().form_valid(form)
def get_success_url(self):
reverse_user = self.request.user
return reverse('profile', kwargs={'username': reverse_user})
class CycleUpdateView(BSModalUpdateView):
model = Cycle
template_name = 'blog/cycle_update.html'
form_class = CycleForm
success_message = 'Success: Cycle was updated.'
def get_success_url(self):
reverse_user = self.request.user
return reverse('profile', kwargs={'username': reverse_user})
We can slightly alter the CycleForm form and add a user parameter. If that parameter is set, we filter the queryset of the posts field by only using Posts
class CycleForm(BSModalForm):
def __init__(self, *args, user=None, **kwargs):
super().__init__(*args, **kwargs)
if user is not None:
self.fields['posts'].queryset = Post.objects.filter(author=user)
class Meta:
model = Cycle
fields = ['title', 'description', 'posts']
widgets = {
'posts': forms.CheckboxSelectMultiple(),
}
Now we only need to pass the user to the form, we can override the get_form_kwargs method [Django-doc]:
class CycleCreateView(LoginRequiredMixin, BSModalCreateView):
template_name = 'blog/cycle_form.html'
form_class = CycleForm
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs.update(user=self.request.user)
return kwargs
def form_valid(self, form, **kwargs):
form.instance.author = self.request.user
return super().form_valid(form)
def get_success_url(self):
reverse_user = self.request.user
return reverse('profile', kwargs={'username': reverse_user})
You should do the same with the UpdateView. Note that your LoginRequiredMixin likely should be put first in the base classes.
I'm developing the web site where users can register and edit their information. I would like to use multi form in the single page. I can develop register form using CreateView. But when I use UpdateVIew, I don't know how to add initial value in multi form.
My code(view.py) is below. I can add form data as initial value, but not form2. Please tell me how to add form2 data as initial value.
▪️view.py
class UserUpdate(OnlyYouMixin, generic.UpdateView):
model = Profile
form_class = ProfileForm
second_form_class = ProfileNearStationForm
template_name = 'accounts/user_form.html'
def get_context_data(self, **kwargs):
context = super(UserUpdate, self).get_context_data(**kwargs)
if 'form' not in context:
context['form'] = self.form_class(self.request.GET, instance=self.request.user)
if 'form2' not in context:
context['form2'] = self.second_form_class(self.request.GET, instance=self.request.user)
return context
def get(self, request, *args, **kwargs):
super(UserUpdate, self).get(request, *args, **kwargs)
form = self.form_class
form2 = self.second_form_class
return self.render_to_response(self.get_context_data())
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.form_class(request.POST, instance=self.request.user)
form2 = self.second_form_class(request.POST, instance=self.request.user)
if form.is_valid() and form2.is_valid():
profile = form.save(commit=False)
profile.save()
station = form2.save(commit=False)
station.user = user
station.save()
messages.success(self.request, 'Settings saved successfully')
return HttpResponseRedirect(self.get_success_url())
else:
return self.render_to_response(
self.get_context_data(form=form, form2=form2))
def get_success_url(self):
return resolve_url('accounts:user_form', pk=self.kwargs['pk'])
▪️form.py
class ProfileForm(forms.ModelForm):
name = forms.CharField(required=True)
tel_number = forms.CharField(required=True)
class Meta:
model = Profile
fields = ('name', 'tel_number')
class ProfileNearStationForm(forms.ModelForm):
prefecture = forms.ModelChoiceField(queryset=areas_model.Prefecture.objects.all(), required=True)
railway = forms.ModelChoiceField(queryset=areas_model.Railway.objects.none(), required=True)
station = forms.ModelChoiceField(queryset=areas_model.Station.objects.none(), required=True)
memo = forms.CharField(required=False)
class Meta:
model = ProfileNearStation
fields = ('prefecture', 'railway', 'station', 'memo')
▪️model.py
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=255)
tel_number = models.CharField(max_length=13)
class ProfileNearStation(models.Model):
prefecture = models.ForeignKey(areas_model.Prefecture, on_delete=models.CASCADE)
railway = models.ForeignKey(areas_model.Railway, on_delete=models.CASCADE)
station = models.ForeignKey(areas_model.Station, on_delete=models.CASCADE)
memo = models.CharField(max_length=255, null=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
I am not good at English.
Please understand me.
I'm creating a blog in Django.
I am making it into class view, but I want to see a reple list and form in the post details view.
like this
enter image description here
POST detailview has already been implemented and I don't know how to add comments.
Should I be function view?
Give me some advice.
code
views.py
class BlogLV(LoginRequiredMixin,ListView):
model = Blog
def get_queryset(self):
return Blog.objects.exclude(user=self.request.user)
class BlogCV(LoginRequiredMixin,CreateView): # blog_form.html
model = Blog
fields = ['name','description','image']
success_url = reverse_lazy('blog:index')
def form_valid(self, form): #오류
form.instance.user = self.request.user #user 설정
form.instance.slug = self.request.user
return super(BlogCV,self).form_valid(form)
class BlogDV(LoginRequiredMixin,DetailView):
model = Blog
class PostCreateView(LoginRequiredMixin,CreateView):
model = Post
fields = ['title', 'content']
success_url = reverse_lazy('blog:index')
template_name = 'blog/post_form.html'
def get_context_data(self, **kwargs):
context = super(PostCreateView, self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.slug = self.request.user
return super(PostCreateView, self).form_valid(form)
class PostDV(LoginRequiredMixin,DetailView):
model = Post
fields =['title','content']
def get_context_data(self, **kwargs):
context = super(PostDV, self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
class PostLV(LoginRequiredMixin,ListView):
model = Post
paginate_by = 5
def get_context_data(self, *, object_list=None, **kwargs):
context = super(PostLV,self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
def get_queryset(self):
return Post.objects.filter(slug=self.kwargs['slug'])
class PostDeleteView(LoginRequiredMixin,DeleteView):
model = Post
success_url = reverse_lazy('blog:index')
def get_context_data(self, *, object_list=None, **kwargs):
context = super(PostDeleteView,self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
class PostUV(LoginRequiredMixin,UpdateView):
model = Post
fields = ['title','content']
success_url = reverse_lazy('blog:index')
def get_context_data(self, *, object_list=None, **kwargs):
context = super(PostUV,self).get_context_data(**kwargs)
context['blog'] = Blog.objects.get(slug=self.kwargs['slug'])
return context
urls.py
urlpatterns = [
url(r'^$',BlogLV.as_view(),name="index"),
url(r'^create/$',BlogCV.as_view(),name='blog_create'),
url(r'^(?P<slug>[-\w]+)/$',BlogDV.as_view(),name='blog_detail'),
url(r'^(?P<slug>[-\w]+)/post/create/$',PostCreateView.as_view(),name='post_create'),
url(r'^(?P<slug>[-\w]+)/post/$',PostLV.as_view(),name='post_list'),
url(r'^(?P<slug>[-\w]+)/post/(?P<pk>[0-9]+)/$', PostDV.as_view(), name='post_detail'),
url(r'^(?P<slug>[-\w]+)/update/(?P<pk>[0-9]+)/$', PostUV.as_view(), name='post_update'),
url(r'^(?P<slug>[-\w]+)/delete/(?P<pk>[0-9]+)/$', PostDeleteView.as_view(), name='post_delete'),
]
models.py
#python_2_unicode_compatible
class Blog(models.Model): # 유저 당 하나
name = models.CharField(max_length=20)
description = models.CharField(max_length=30)
image = models.ImageField(upload_to='blog/profile')
create_date = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(unique=True,allow_unicode=True)
# 블로그 생성한 시각
# 저장 경로: MEDIA_ROOT/blog/projile/xxx.jpg 파일 저장
# DB 필드 'MEDIA_URL/blog/profile/xxx.jpg' 문자열 저장
user = models.OneToOneField(User)
class Meta:
ordering = ['-create_date']
# 생성된 날짜의 내림차순으로 정렬
def __str__(self):
return self.name
#python_2_unicode_compatible
class Post(models.Model):
title = models.CharField(max_length=30)
content = models.TextField()
create_date = models.DateTimeField(auto_now_add=True)
modify_date = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User)
slug = models.SlugField(allow_unicode=True,default='slug')
class Meta :
ordering = ['-create_date']
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('blog:post_detail',args=(self.id,))
# post.get_absolute_url args
# 객체가 지칭하는 url 반환
def get_previous_post(self):
return self.get_previous_by_create_date()
#create_date 기준으로 이전 포스트 반환
# get_previous_by_column 내장객체 호출
def get_next_post(self):
return self.get_next_by_create_date()
#python_2_unicode_compatible
class Reple(models.Model):
content = models.TextField()
user = models.ForeignKey(User)
Post = models.IntegerField() # post_id
create_date = models.DateTimeField(auto_now_add=True)
class Meta:
ordering = ['-create_date']
def __str__(self):
return self.content
It's my first time writing, so I don't know how to Indent. Sorry
And if my code is not effective, tell me how to fix it.
thank you!
It might be easier to write the view from scratch as a function, but you can also override the existing post method to return additional data.