I am trying to create a query to grab the pk of the current post from the database. Then set it as the foreign key of the new post. I am using formview, and the model I am trying to retrieve the 'id' from is called Projects. Id is the primary key of the model Projects.
How would I be able to go about this?
pk=5 because I didn't know how to get the current one.
views.py
class ProjectDetailToDoForm(FormView):
model = ProjectsToDo
form_class = ProjectToDoForm
success_url = '../..'
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(ProjectDetailToDoForm, self).dispatch(request, *args, **kwargs)
def form_valid(self,form):
self.object = form.save(commit=False)
self.object.project = Projects.objects.get(pk=5)
self.object.save()
return super(ProjectDetailToDoForm, self).form_valid(form)
class ProjectDetail(generic.DetailView):
model = Projects
context_object_name = 'indprojects'
template_name = 'projectpage.html'
def get_context_data(self, *args, **kwargs):
context = super(ProjectDetail, self).get_context_data(*args, **kwargs)
context['todolist'] = ProjectsToDo.objects.order_by('project_tododate')
context['todoform'] = ProjectToDoForm()
context['form'] = ProjectForm(instance=Projects.objects.get(slug=self.kwargs['slug']))
return context
def get_queryset(self):
return Projects.objects.filter(user=self.request.user)
#method_decorator(login_required)
def dispatch(self, request, *args, **kwargs):
return super(ProjectDetail, self).dispatch(request, *args, **kwargs)
models.py
class Projects(models.Model):
user = models.ForeignKey(User)
slug = models.SlugField()
project_title = models.CharField(max_length=30)
project_shortdesc = models.CharField(max_length=248)
project_desc = models.TextField()
def save(self):
super(Projects, self).save()
date = datetime.date.today()
self.slug = '%i%i%i%s' % (
date.year, date.month, date.day, slugify(self.project_title)
)
super(Projects, self).save()
class ProjectsToDo(models.Model):
project_tododate = models.DateField()
project_tododesc = models.TextField(max_length = 500)
project = models.ForeignKey(Projects)
def __unicode__(self):
return '%s %s' % (self.project_tododesc, self.project_tododate)
I am guessing that you define the active project using the url. In that case, you can do something like this:
urls.py
url(r'^(?P<project_slug>[\w-]+)/add_todo/$',
views.ProjectDetailToDoForm.as_view(),
name='add_todo',
),
...
view
def form_valid(self, form):
self.object = form.save(commit=False)
project = Project.objects.get(slug=self.kwargs["project_slug"])
self.object.project = project
self.object.save()
return super(ProjectDetailToDoForm, self).form_valid(form)
Related
I dont know why i am getting this error I am trying build an admin panel.So I am trying to make create category functionality after coding all the functionalities i got stuck in this error
Here is my view.py
def createcategory(request):
if request.method == 'POST':
createcat = CategoryForm(request.POST, request.FILES)
if createcat.is_valid():
cat_name = createcat.cleaned_data['category_name']
cat_image = createcat.cleaned_data['category_image']
insert_cat = CategoryModel(
category_name=cat_name, category_image=cat_image)
insert_cat.save()
create2 = CategoryForm()
return render(request, 'createcat.html', {'create2': createcat})
else:
createcat = CategoryForm()
all_categories = CategoryModel.object.all()
return render(request, 'index.html')
Here is my models.py
class CategoryModel(models.Model):
category_id = models.AutoField(primary_key=True)
category_name = models.CharField(max_length=100)
category_image = models.ImageField(upload_to='images/')
I am giving the category model I created in the code example below as an example. Which model category you create is very important.
You also need to save the model you created in admin.py.
models.py
class Category(models.Model):
title = models.CharField(max_length=150)
slug = models.SlugField(editable=False)
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Category, self).save(*args, **kwargs)
def task_count(self):
return self.task.count()
class Task(models.Model):
user = models.ForeignKey("auth.User", on_delete=models.CASCADE, verbose_name='TaskUser') # user
title = models.CharField(max_length=150, verbose_name='Task Title')
content = RichTextField()
created_date = models.DateTimeField(auto_now_add=True, verbose_name='Task Date')
slug = models.SlugField(editable=False)
category = models.ForeignKey(Category, on_delete=models.CASCADE, related_name="task")
def __str__(self):
return self.title
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(Task, self).save(*args, **kwargs)
As you can see I add a category field in the task model.
views.py
class IndexView(ListView):
template_name = 'task/index.html'
model = Task
context_object_name = 'task'
# paginate_by = 7
def get_context_data(self, *, object_list=None, **kwargs):
context = super(IndexView, self).get_context_data(**kwargs)
return context
class CategoryDetail(ListView):
model = Task
template_name = 'category/category_detail.html'
context_object_name = 'task'
# paginate_by = 3
def get_queryset(self):
self.category = get_object_or_404(Category,
pk=self.kwargs['pk'])
return Task.objects.filter(category=self.category).order_by('-id')
def get_context_data(self, *, object_list=None, **kwargs):
context = super(CategoryDetail, self).get_context_data(**kwargs)
self.category = get_object_or_404(Category, pk=self.kwargs['pk'])
# context['category'] = self.category
return context
Finally, I am registering in admin.py.
admin.py
admin.site.register(Task)
admin.site.register(Category)
I hope it helped.
You only return at one condition, if it's at POST, else you don't. so please add a default return at the end.
just like:
if `POST`:
...
return render(request, 'createcat.html', {'create2': createcat})
else:
return render(request, 'default.html')
PS: using the below code format indention:
def createcategory(request):
if request.method == 'POST':
createcat = CategoryForm(request.POST, request.FILES)
if createcat.is_valid():
cat_name = createcat.cleaned_data['category_name']
cat_image = createcat.cleaned_data['category_image']
insert_cat = CategoryModel(
category_name=cat_name, category_image=cat_image)
insert_cat.save()
create2 = CategoryForm()
return render(request, 'createcat.html', {'create2': createcat})
else:
createcat = CategoryForm()
all_categories = CategoryModel.object.all()
return render(request, 'index.html')
# print("test")
PS2: Want to show form.
def createcategory(request):
createcat = CategoryForm(request.POST, request.FILES) # put your form here
if request.method == 'POST':
if createcat.is_valid():
cat_name = createcat.cleaned_data['category_name']
cat_image = createcat.cleaned_data['category_image']
insert_cat = CategoryModel(
category_name=cat_name, category_image=cat_image)
insert_cat.save()
create2 = CategoryForm()
return render(request, 'createcat.html', {'create2': createcat})
all_categories = CategoryModel.object.all() # make sure you know this line.
return render(request, 'index.html', createcat) # put your empty form here
I can't figure out why my validators doesn't work at all.
Form is not invalid
Model doesn't raise ValidationError when being saved
For input: "123456sdad"
I have a model which has broker_ico field:
REGEX_ICO = r"\d{6,8}"
broker_ico = models.CharField(max_length=100, verbose_name='IČO',
validators=[RegexValidator(REGEX_ICO)])
I've overwritten save method:
def save(self, **kwargs):
print('full clean')
self.full_clean()
super().save(**kwargs)
Moreover the form is a ModelForm:
class BusinessCaseDocumentForm(ModelForm):
class Meta:
model = BusinessCaseDocument
exclude = ['id','business_case']
def __init__(self, *args, **kwargs):
super(BusinessCaseDocumentForm, self).__init__(*args, **kwargs)
for field_name, field in self.fields.items():
fs_helpers.add_widget_attribute('class', 'form-control', field)
UpdateView:
class BusinessCaseDocumentUpdateView(SuccessMessageMixin, UpdateView):
model = BusinessCaseDocument
form_class = BusinessCaseDocumentForm
template_name = "business_cases/businesscase_documents/create.html"
success_message = "Podklad k obchodnému prípadu bol upravený"
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['businesscase'] = self.object.business_case # TODO self.businesscase set
return context
def get_success_url(self):
return reverse("business_cases:list")
Can you see where is the problem?
I have an item. An item can have many reviews. I expect a review to be created within the context of an item. Therefore, I capture the pk from the url and add it to the context.
This is where I get stuck, I'm unsure how to access the context in form_valid and, more importantly, I'm concerned the path I'm trying to go down seems hacky.
Essentially when the user prepares to submit a review, the application will know what item it's in reference to. What's the most pythonic/django-onic way to do this?
Models
class Item(models.Model):
name = models.CharField(max_length=100)
source = models.ForeignKey('Source')
class Review(models.Model):
rating = models.CharField(max_length=30)
value = models.CharField(max_length=30)
date = models.DateField(auto_now_add=True)
comment = models.CharField(blank=True,max_length=100)
item = models.ForeignKey(Item,blank=True)
user = models.ForeignKey(User)
Urls
url(r'^review/create/item/(?P<itempk>\d+)',views.ReviewCreate.as_view(),name='review_create'),
Views
class ReviewCreate(CreateView):
model = Review
fields = ['rating', 'value', 'comment']
def get_context_data(self, **kwargs):
context = super(ReviewCreate, self).get_context_data(**kwargs)
itempk = self.kwargs['itempk']
item = get_object_or_404(Item, pk=itempk)
context['item'] = item
return context
def form_valid(self, form):
review = form.save(commit=False)
review.user = self.request.user
context = super(ReviewCreate, self).get_context_data(**kwargs) '''doesn't work'''
review.item = context['item']
return super(ReviewCreate, self).form_valid(form)
template_name = 'food/review_form.html'
The get_context_data method is meant to return the context for a template, so I agree that calling it in form_valid is a bit hacky.
You could fetch the item in the dispatch method instead and store it as self.item. Then you can retrieve the item in get_context_data and form_valid.
In form_valid you can modify form.instance - that way you don't have to save with commit=False.
class ReviewCreate(CreateView):
model = Review
fields = ['rating', 'value', 'comment']
def dispatch(self, request, *args, **kwargs):
itempk = self.kwargs['itempk']
self.item = get_object_or_404(Item, pk=itempk)
return super(ReviewCreate, self).dispatch(request, *args, **kwargs)
def get_context_data(self, **kwargs):
context = super(ReviewCreate, self).get_context_data(**kwargs)
context['item'] = self.item
return context
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.item = self.item
return super(ReviewCreate, self).form_valid(form)
template_name = 'food/review_form.html'
I am trying to pass a kwarg from CreateView to a ModelForm so I can dynamically adjust the fields based on values in the related Parent object. Other answers have indicated that passing a kwarg by overriding get_form_kwargs in the view and catching it with kwarg.pop in the form should work, but I get an AttributeError: 'ChildForm' has no attribute 'get' when I try. Passing the kwarg into the view context works, but doesn't give me access to the value inside the form instance.
models.py:
class Parent(models.Model):
name = models.CharField(max_length=255)
details = models.CharField(max_length=255)
detailstwo = models.CharField(max_length=255, null=True)
child_mod = models.BooleanField(default=False)
slug = models.SlugField()
creator = models.ForeignKey(User)
def save(self, *args, **kwargs):
if not self.id:
self.slug = slugify(self.name)
super(Parent, self).save(*args, **kwargs)
def __str__(self):
return self.name
class Child(models.Model):
parent = models.ForeignKey(Parent)
parent_mod = models.CharField(max_length=255)
child_name = models.CharField(max_length=255)
def __unicode__(self):
return self.child_name
views.py:
class ChildCreateView(CreateView):
model = Child
form_class = ChildForm
template_name = 'testapp/child_form.html'
def dispatch(self, *args, **kwargs):
return super(ChildCreateView, self).dispatch(*args, **kwargs)
def get_form_kwargs(self, **kwargs):
kwargs = super(ChildCreateView, self).get_form_kwargs()
parent = get_object_or_404(Parent, slug=self.kwargs['parent_slug'])
kwargs['parent'] = parent
return kwargs
def get_context_data(self, **kwargs):
context = super(ChildCreateView, self).get_context_data(**kwargs)
parent = get_object_or_404(Parent, slug=self.kwargs['parent_slug'])
context['parent'] = parent
return context
def form_valid(self, form):
child = form.save(commit=False)
parent_slug = form.data['parent_slug']
parent = get_object_or_404(Parent, slug=parent_slug)
child.parent = parent
return super(ChildCreateView, self).form_valid(form)
def get_success_url(self):
return reverse('testapp:parent_view', kwargs={'slug': self.object.parent.slug})
forms.py:
class ChildForm(forms.ModelForm):
class Meta:
model = Child
fields = ['parent', 'parent_mod', 'child_name']
def __init__(self, *args, **kwargs):
self.parent_object = kwargs.pop('parent')
assert isinstance(self.parent_object, Parent)
super(ChildForm, self).__init__(self, *args, **kwargs)
self.fields["parent_slug"] = forms.CharField(widget=forms.HiddenInput())
if not self.parent_object.child_mod:
del self.fields['parent_mod']
Full Traceback is here: http://dpaste.com/2QBMRJX
I'm practicing Django's generic views, particularly ModelForms
These are my views and models
models.py
class Post(models.Model):
user = models.ForeignKey(User)
post_title = models.CharField(max_length=200)
post_content = models.CharField(max_length=500)
post_date = models.DateTimeField('date posted')
def get_absolute_url(self):
return reverse('user-detail', kwargs={'pk': self.pk})
def __unicode__(self):
return self.post_title
forms.py
class PostForm(forms.ModelForm):
post_title = forms.CharField(
label=u'Title',
widget=forms.TextInput(attrs={'size':64})
)
post_content = forms.CharField(
label=u'Content',
widget=forms.TextInput(attrs={'size':128})
)
class Meta:
model = Post
views.py
class PostCreate(CreateView):
fields = ['post_title', 'post_content']
template_name = 'app_blog/post_save_form.html'
model = Post
form_class = PostForm
#method_decorator(login_required)
def dispatch(self, *args, **kwargs):
return super(PostCreate, self).dispatch(*args, **kwargs)
def form_valid(self, form):
self.object = form.save(commit=False)
self.object.user = self.request.user
self.object.post_date = datetime.now()
return super(PostCreate, self).form_valid(form)
The view seems to work fine, not displaying any errors. However, when I check the Django admin page after submitting a form and saving a post, the post is not saved into the database for some reason.
Any idea why this is happening?
As I can see from your code you use
self.object = form.save(commit=False)
which mean that object will not be saved to database, but you can use it for futher processing. So you should use something like this:
self.object = form.save(commit=False) # Not hit database
self.object.user = self.request.user # Update user
self.object.post_date = datetime.now() # Update post_date
self.object.save() # And finally save your object to database.
Try this.
def form_valid(self, form):
form.instance.user = self.request.user
form.instance.post_date = datetime.now()
return super(PostCreate, self).form_valid(form)