I have some problem
This is my code:
views.py:
def cv_detail(request, pk):
cv = get_object_or_404(Cv, pk=pk)
return render(request, 'cv_detail.html', {'cv': cv})
cv_detail.html:
{% block profile %}
<a class="btn-lg btn-default" href="{% url "edit_cv" pk=cv.pk %}"><span class="glyphicon glyphicon-pencil"> Edit</span></a>
<p></p><br>
<div class="jumbotron">
{% if not cv.specialization.is_empty %}
<p>Specialization: {{cv.specialization}}</p>
{% endif %}
</div>
{% endblock %}
forms.py:
class CvForm(forms.ModelForm):
class Meta:
model = Cv
fields = ('name', 'specialization',)
models.py:
class Cv(models.Model):
author = models.ForeignKey('auth.User')
name = models.CharField(max_length=25, null = True)
specialization = models.CharField(max_length=30, blank=True, null=True)
def zapisz(self):
self.save()
def __str__(self):
return self.surname
And the question is: how can i check is any field of cv model is empty?
I have nothing in "Specialization" - is not complemented by me, so shouldn't be displayed, but it is, like: "Specialization: ".
Any ideas how to check? Becouse that what i have is not working :/
Thanks!
You can check for an empty specialization field in your template with:
{% if cv.specialization and cv.specialization.strip %}
<p>Specialization: {{cv.specialization}}</p>
{% endif %}
The .strip check will ensure that you do not attempt to display a string that only contains whitespaces.
Related
I'm trying to build a structure using Django Rest Framework to show some data in my html templates. But I can't show data from a model with ForeignKey.
My structure should be like this:
{% for category in categories %}
{{ category.category }} #category is the variable name
{% for channel in category.channel_set.all %}
{{ channel.title }}
{{ endfor }}
{{ endfor }}
But I can't print the channel variables in html files.
models.py:
class Category(models.Model):
user = models.ForeignKey(
'auth.User',
on_delete=models.DO_NOTHING,
unique=False,
)
category = models.CharField(
max_length=255,
unique=True,
)
_id = models.ObjectIdField(auto_created=True, serialize=False)
event_creation = models.DateTimeField(auto_now=True)
event_updated = models.DateTimeField(auto_now=True)
class Meta:
db_table = 'category'
verbose_name = 'category'
verbose_name_plural = 'categories'
def __str__(self):
return self.category
class Channel(models.Model):
user = models.ForeignKey(
'auth.User',
on_delete=models.DO_NOTHING,
)
_id = models.ObjectIdField(auto_created=True, serialize=False)
date_creation = models.DateTimeField(auto_now=True)
date_updated = models.DateTimeField(auto_now=True)
category = models.ForeignKey(
Category,
max_length=255,
on_delete=models.PROTECT,
related_name='channel',
unique=False,
to_field='category',
)
channel = models.CharField(
max_length=255,
unique=True,
)
def __str__(self):
return self.category
views.py:
class Gallery(viewsets.ModelViewSet):
renderer_classes = [TemplateHTMLRenderer]
template_name = '/gallery.html'
queryset = Category.objects.all()
queryset2 = Channel.objects.all()
permission_classes = [permissions.IsAuthenticated]
def get(self, request, **kwargs):
kwargs['categories_list'] = self.queryset
serializer = CategorySerializer(self.queryset,many=True)
serializer2 = ChannelSerializer(self.queryset2,many=True)
return Response({
'categories':serializer.data,
'channels':serializer2.data
})
# #login_required(login_url='/login/')
def list(self, request):
queryset = Category.objects.all()
response = {'categories': queryset}
return Response({'categories':queryset})
serializers.py:
class CategorySerializer(serializers.ModelSerializer):
# _id = serializers.ReadOnlyField()
categories = Category()
class Meta:
model = Category
fields = '__all__'
class ChannelSerializer(serializers.ModelSerializer):
# _id = serializers.ReadOnlyField()
channels = Channel()
class Meta:
model = Channel
fields = '__all__'
gallery.html:
{% extends "/model-page.html" %}
{% load core_tags %}
{% block content %}
<h1> co. </h1>
<h2> Last Archives </h2>
<a href="/category-api/">
<button type="button"> New input </button>
</a>
<ul>
{% for category in categories %}
<td> {% underscoreTag category "_id" as category_id %} </td>
<div {% if category.get_pass_event %} style="color: red "{% endif %}>
<li>{{ category.category }} - {{ category.get_creation }}
<ul>
<li>{{ category }}</li>
<ul>
<div>
{% for channel in category.channel_set.all %}
<li>Teste {{ channel.title }}</li>
{% endfor %}
</div>
</ul>
</ul>
Edit /
Delete
</li>
</div>
{% endfor %}
</ul>
{% endblock %}
I had trying for {% for channel in category.channel_set.all %},{% for channel in category.channels_set.all %}, {% for channel in category.channel.all %} and {% for channel in category.channels.all %} and any of these worked for me.
Another info from my project is that I'm using Django (because my database is MongoDB).
I think the code of the serializers isn't correct.
class ChannelSerializer(serializers.ModelSerializer):
class Meta:
model = Channel
fields = '__all__'
class CategorySerializer(serializers.ModelSerializer):
channel = ChannelSerializer(many = True, read_only = True)
class Meta:
model = Category
fields = '__all__'
And in the html, some attributes don't exist in the models. channel_set should be changed into channel and channel.title into channel.channel.
There are no names like channel_set, title in the models.
...
<ul>
<div>
{% for channel in category.channel %}
<li>Teste {{ channel.channel }}</li>
{% endfor %}
</div>
</ul>
...
Or you should modify the names in the models.
So in short, I have a ListView in Django which displays pictures with tables on the website. Then I have a DetailView where I am placing a second webpage to use with slugs but I guess my logic is wrong.
I want to be able to click on a particular picture/ table and this would redirect me to another page( possible created with slug) where I can display more pictures of the same table. I have created everything so far but I am thinking my logic is wrong. You don't have to write code, just please explain what is the correct way of doing it since I am doing it for the first time.
First I created a Categories model which lists categories such as: tables, kitchens, wardrobes, bedrooms. I then created Image category where I would have title and image and so on but this was okay for one of the views but for this one I want to display multiple pictures as I mentioned and I saw some code which enabled me to have multiple images.
views.py
class TableCategoryListView(ListView):
model = Images
template_name = 'main/projects/tables.html'
context_object_name = 'category_images'
queryset = Images.objects.filter(category__category_title="tables")
class TablesDetailView(DetailView):
model = Images
template_name = "main/projects/tables_slug.html"
url.py
path('proekti/masi/', TableCategoryListView.as_view(), name='tables'),
path('proekti/masi/<slug:slug>', TablesDetailView.as_view(), name='table'),
models.py
class Category(models.Model):
category_title = models.CharField(
max_length=50
)
def __str__(self):
return self.category_title
class Images(models.Model):
title = models.CharField(
blank=True,
null=True,
max_length=50,
)
category_image = models.ImageField(
blank=True,
null=True,
)
category = models.ForeignKey(
Category,
on_delete=models.CASCADE)
def __str__(self):
return self.title
def __unicode__(self):
return self.title
slug = models.SlugField(
null=True,
)
def get_absolute_url(self):
return reverse("article-detail", kwargs={"slug": self.slug})
class PhotoAlbum(models.Model):
menu = models.ForeignKey(Images, on_delete=models.CASCADE)
image = models.ImageField()
order = models.IntegerField(
blank=True,
null=True,
)
def __unicode__(self):
return self.menu
class Meta:
ordering = ('order',)
I read this would help me to easily add multiple pictures.
admin.py
#admin.register(Category)
class CategoryAdmin(admin.ModelAdmin):
pass
class ImagesForm(forms.ModelForm):
model = Images
class Media:
js = (
'/static/js/jquery-latest.js',
'/static/js/ui.base.js',
'/static/js/ui.sortable.js',
'/static/js/menu-sort.js',
)
class PhotoAlbumInline(admin.StackedInline):
model = PhotoAlbum
admin.site.register(
Images,
inlines=[PhotoAlbumInline],
form=ImagesForm,
list_filter=('category',),
search_fields=('title',)
)
"""
/* menu-sort.js */
jQuery(function($) {
$('div.inline-group').sortable({
/*containment: 'parent',
zindex: 10, */
items: 'div.inline-related',
handle: 'h3:first',
update: function() {
$(this).find('div.inline-related').each(function(i) {
if ($(this).find('input[id$=name]').val()) {
$(this).find('input[id$=order]').val(i+1);
}
});
}
});
$('div.inline-related h3').css('cursor', 'move');
$('div.inline-related').find('input[id$=order]').parent('div').hide();
});
"""
template tables.html
{% extends 'base.html' %}
{% block page_content %}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/masi.css' %}">
<div class="row">
{% for image in object_list %}
{% if forloop.counter0|divisibleby:1 %}
<div class="column" style="background-color: whitesmoke">
<img src="{{ image.category_image.url }}" alt="pic">
<p>
</div>
{% endif %}
{% endfor %}
</div>
{% endblock %}
template tables_slug.html --> where I would want to display all the images of a particular table with it doesn't show me one of the tables and doesn't show all the images I have uploaded in the admin page.
{% extends 'base.html' %}
{% block page_content %}
{% for image in category_images %}
<div>
<h2>{{ object.title }} </h2>
<img src="{{ object.category_image.url }}" alt="pic">
</div>
{% endfor %}
{% endblock %}
Updated
You can do this:
In your TableCategoryListView, override the get_context_data like so:
class TableCategoryListView(ListView):
model = Images
template_name = 'main/projects/tables.html'
context_object_name = 'category_images'
class TableCategoryListView(ListView):
model = Images
template_name = 'main/projects/tablesdetail.html'
context_object_name = 'detail_cat_img'
def get_context_data(self, **kwargs):
context = super(TableCategoryListView, self).get_context_data(**kwargs)
context['detail_category'] = Images.objects.all() # this gives you all the items from the Images model
context['xtr_images'] = PhotoAlbum.objects.all() # the logic to render only those photos related to the current view goes here. You have to figure this out yourself
return context # this returns the two objects above xtr_images and detailcategory
You can use the slice operator to determine number of images to show per page either in your views or on the template itself like so:
Entry.objects.all()[:5] # prints four images
This should do the trick.
Thanks for your answer.I just solved the problem I believe with simpler code.
I was missing "related_names" in the model for the relation.
models.py
class PhotoAlbum(models.Model):
menu = models.ForeignKey(
Images,
on_delete=models.CASCADE,
related_name="child_images",
)
image = models.ImageField()
order = models.IntegerField(
blank=True,
null=True,
)
def __unicode__(self):
return self.menu
class Meta:
ordering = ('order',)
and for the template then: tables_slug.html
{% extends 'base.html' %}
{% block page_content %}
{% load static %}
<link rel="stylesheet" type="text/css" href="{% static 'css/masi.css' %}">
{% for image in image.child_images.all %}
<div class="column">
<p>
<img src="{{ image.image.url }}" alt="pic">
</p>
</div>
{% endfor %}
{% endblock %}
how can I retrieve the lesson modules by its parent lesson strictly? e.g if I change to the next lesson where at the same contains a lessonmodule /lesson1/task1 this one shouldn't display since it doesn't belong to lesson2? how can I fix this by only retrieve slugs, content by the lesson attach to?
views
class LessonDetailView(LoginRequiredMixin, View):
login_url = "/account/login/"
def get(self, request, course_slug, lesson_slug, *args, **kwargs):
lesson = get_object_or_404(Lesson.objects.select_related('course'), slug=lesson_slug, course__slug=course_slug)
lessonmodule = get_object_or_404(LessonModule.objects.select_related('lesson'), slug='hello_world')
context = {
'object': lessonmodule,
'previous_lesson': lesson.get_previous_by_created_at,
'next_lesson': lesson.get_next_by_created_at,
}
return render(request, "courses/lesson_detail.html", context)
models
class Lesson(models.Model):
title = models.CharField(max_length=120)
slug = models.SlugField(max_length=25,unique=True)
course = models.ForeignKey(Course, on_delete=models.CASCADE)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('lesson-detail',
kwargs={
'course_slug': self.course.slug,
'lesson_slug': self.slug
})
class LessonModule(models.Model):
slug = models.SlugField(unique=True, blank=True, null=True)
content = models.TextField()
lesson = models.ForeignKey(Lesson, on_delete=models.CASCADE)
allowed_memberships = models.ManyToManyField(Membership)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
updated_at = models.DateTimeField(auto_now=True, blank=True)
def __str__(self):
return self.slug
template
{% block content %}
<div class='container'>
<h1>Lesson Detail View</h1>
<div class='row'>
<div class='col-sm-6 col-md-6'>
{% if object is not None %}
<h3>{{ object.title }}</h3>
<p>{{ object.course.description }}</p>
{{object}}
{% if previous_lesson %}
Back
{% endif %}
{% if next_lesson %}
Next
{% endif %}
{% else %}
<h3>Upgrade membership</h3>
<p>To view this course you'll need to upgrade your membership</p>
<br>
<hr>
{% endif %}
</div>
</div>
</div>
{% endblock content %}
As I can see here, you can have multiple LessonModule for a single Lesson due to one-to-many relation between Lesson and LessonModule(ForeignKey relation basically). You can fetch all the LessonModules like this(using reverse query):
# view
def get(self, request, course_slug, lesson_slug, *args, **kwargs):
lesson = get_object_or_404(Lesson.objects.select_related('course').prefetch_related('lessonmodule_set'), slug=lesson_slug, course__slug=course_slug)
context = {
'object': lesson,
'previous_lesson': lesson.get_previous_by_created_at,
'next_lesson': lesson.get_next_by_created_at,
}
return render(request, "courses/lesson_detail.html", context)
# template
{% for lesson_module in object.lessonmodule_set.all %}
{{ lesson_module.slug }}
{% endfor %}
I am just sending the Lesson object to template, and using reverse query in template to get LessonModule objects.
First of all I want to apologize for my English. It's hard for me to write this question in English, but I didn't find any ideas for my problem on russian sites. So, I want to create a timetable on school-site. In my models.py :
class Classes(models.Model):
class Meta:
db_table = 'classes'
verbose_name_plural = "School_classes"
verbose_name = "School_class"
name = models.CharField(max_length=50, unique=True, verbose_name = 'School_classes')
def __str__(self):
return self.name
class Lessons(models.Model):
class Meta():
db_table = "lessons"
verbose_name_plural = "Lessons"
verbose_name = "Lessons"
lessons_class = models.ForeignKey(Classes)
lessons_creationdate = models.DateField()
lessons_weekcontent = RichTextField()
Then, in forms.py I have:
class LessonsForm(forms.ModelForm):
classname = forms.ModelChoiceField(queryset = Classes.objects.all(),empty_label="Choose a class",widget=forms.Select(attrs={'class':'dropdown'}),label="School_classes")
class Meta:
model = Lessons
fields = ('lessons_class',)
And in my views.py:
def ShowTimetable(request):
LForm = LessonsForm(request.POST or None)
args = {}
args['classes'] = Classes.objects.all()
args['lessons'] = Lessons.objects.all()
args['showlessons'] = LForm
args.update(csrf(request))
if request.method == 'POST' and LForm.is_valid():
CurrentClass = LForm.cleaned_data('currentclass', None)
args['class_name'] = CurrentClass
args['lessons'] = Lessons.objects.filter(lessons_class = CurrentClass)
if args['lessons']:
return render_to_response('Weekcontentpage.html',args )
else:
return render_to_response('Weekcontentpage_null.html',args )
else:
return render_to_response('myview.html',args )
Finally, in myviews.html
{% extends 'base.html' %}
{% block content %}
<form method="post">
{% csrf_token %}
{{ showlessons }}
<input type="submit" value="Show timetable">
</form>
{% endblock %}
In Weekcontentpage.html:
{% extends "base.html" %}
{% block content %}
<h4>On request "{{ class_name }}:</h4>
{% for lesson in lessons %}
<h6>Date:{{ lesson.lessons_creationdate }}</h6>
<h4>{{ lesson.lessons_weekcontent }}</h4>
{% endfor %}
{% endblock content %}
and in Weekcontentpage_null.html:
{% extends "base.html" %}
{% block content %}
<h4> On "{{class_name}}" is nothing found :( (</h4>
{% endblock content %}
Now, after I make a choice in the drop down menu and push 'Show timetable' button, I've just see "None" and nothing is found :(. I understand that the problem in views.py, so i cant get a value from drop down, but I don't know how can i fix it. So i would appreciate any help. Thanks and sorry for my English:)
The same way as with any other field.
The problem is that you have defined a form class, but you are not using it in any way at all. Instead of ignoring the form and getting data from request.POST, you should be instantiating the form with the POST data, calling is_valid() on it, then getting the result from form.cleaned_data.
I have been working thorough the DjangoGirls tutorial and was trying to improve on the section on adding comments to an application - TutorialExtensions
I have added the comments to a simple photo blog application but what I was attempting to do was replace the author = models.CharField(max_length=200) with an alternative that would store the current/logged-in user who was commenting on the photo instance and then allow me to display on the photo_detail template.
I thought I was close using author = models.ForeignKey(User, related_name='Commenter') but this through up an error:
NOT NULL constraint failed: timeline_comment.author_id
Here is my models.py consisiting of a Photo model and Comments model:
class Photo(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, default=1)
title = models.CharField(max_length=120)
slug = models.SlugField(unique=True)
image = ProcessedImageField(upload_to=upload_location,
null=True,
blank=False,
processors=[Transpose(), ResizeToFit(1000, 1000, False)],
format='JPEG',
options={'quality': 50},
width_field="width_field",
height_field="height_field")
height_field = models.IntegerField(default=0)
width_field = models.IntegerField(default=0)
description = models.TextField(max_length=1000)
updated = models.DateTimeField(auto_now=True, auto_now_add=False)
timestamp = models.DateTimeField(auto_now=False, auto_now_add=True)
class Comment(models.Model):
post = models.ForeignKey('timeline.Photo', related_name='comments')
author = models.CharField(max_length=200)
text = models.TextField(max_length=1000)
created_date = models.DateTimeField(default=timezone.now)
The related view:
def photo_detail(request, slug=None):
if not request.user.is_authenticated():
return HttpResponseRedirect("/accounts/login")
instance = get_object_or_404(Photo, slug=slug)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = instance
comment.save()
return redirect('timeline:detail', slug=instance.slug)
else:
form = CommentForm()
share_string = quote_plus(instance.description)
context = {
"title": instance.title,
"instance": instance,
"share_string": share_string,
"form": form,
}
return render(request, "photo_detail.html", context)
My forms.py:
class CommentForm(forms.ModelForm):
text = forms.CharField(widget=forms.Textarea, label='Leave a comment: ')
class Meta:
model = Comment
fields = [
"text",
]
Finally the template for the photo_detail view:
<div class="row">
<div class="col-md-12" id="comments">
<p>
{% if instance.comments.count == 0 %}
No Comments
{% elif instance.comments.count == 1 %}
{{ instance.comments.count }} Comment
{% else %}
{{ instance.comments.count }} Comments
{% endif %}
</p>
<hr style="margin-top: 10px;">
{% for comment in instance.comments.all %}
<div class="comment">
<div class="date pull-right">{{ comment.created_date | timesince }} Ago</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
<hr>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
</div>
</div>
{% if user.is_superuser or user.is_authenticated %}
<div class="row">
<div class="col-md-12">
<form method="POST" class="comment-form" action=''>
{% csrf_token %}
{{ form | crispy }}
<button type="submit" class="comment-add btn btn-lg btn-purple">Add</button>
</form>
</div>
</div>
{% endif %}
Could anybody recommend the best approach for this? Any help would be very much appreciated! Thank You.
Using the ForeignKey is correct[1] - the missing piece is that you need to assign that in your view. After comment = form.save(commit=False) just add one line:
comment.author = request.user
and it will work.
[1] although you don't want the related_name as "Commenter" (because it refers to the way you access the comment from the user: the default is comment_set which makes more sense).