django.urls.exceptions.NoReverseMatch
django.urls.exceptions.NoReverseMatch: Reverse for 'for_user' with keyword arguments '{'username': ''}' not found. 1 pattern(s) tried: ['questions/by/(?P<username>[-\\w]+)/$']
i'm getting a no reverse match error however from what i can tell, all the necessary things are there. I have the url which has the username argument which is being given from the html and is being saved into the model and expressed through the view.
im a still a django novice. all help is appreciated.
file structure
usertest - root
-->accounts - appname
-->questions - appname
-->urls.py
-->views.py
-->model.py
templates
-->base.html
urls.py
url(r'by/(?P<username>[-\w]+)/$', views.UserQuestions.as_view(), name="for_user"),
base.html
<nav class="navbar mynav" role="navigation" id="navbar">
<div class="container">
<a class="navbar-brand mynav" href="{% url 'questions:all' %}">WebSiteIcon</a>
<ul class="nav navbar-nav navbar-right">
{% if user.is_authenticated %}
<li>hello {{ question.user }}</li>
<li></li>
<li></li>
<li></li>
<li>Log out</li>
{% else %}
<li>Log in</li>
<li>Sign up</li>
{% endif %}
</ul>
</div>
</nav>
<div class="container mycontent">
model.py
class Question(models.Model):
class Meta:
ordering = ['-date_updated']
user = models.ForeignKey(User, related_name="questions")
question = models.TextField(blank=False, null=False) # unique=True,
question_html = models.TextField(blank=False, null=False)
answer = models.TextField(blank=False, null=False)
answer_html = models.TextField(blank=False, null=False)
date_created = models.DateTimeField(auto_now=True, null=True)
date_updated = models.DateTimeField(auto_now=True, null=True)
slug = models.SlugField(unique=True, default='')
tags = TaggableManager()
def __str__(self):
return self.question
# ^ to display an object in the Django admin site and
# as the value inserted into a template when it displays an object.
def save(self, *args, **kwargs):
self.question_html = misaka.html(self.question)
self.answer_html = misaka.html(self.answer)
super().save(*args, **kwargs)
def get_absolute_url(self):
return reverse(
"questions:detail",
kwargs={
"slug": self.slug,
"pk": self.pk,
"username": self.user.username,
}
)
views.py
class UserQuestions(generic.ListView):
model = models.Question
template_name = "questions/user_question_list.html"
def get_queryset(self):
try:
self.question_user =
User.objects.prefetch_related("questions").get(
username__iexact=self.kwargs.get("username")
)
except User.DoesNotExist:
raise Http404
else:
return self.question_user.questions.all()
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context["question_user"] = self.question_user
return context
{% url 'questions:for_user' username=question.user.username %}
For this url to work, you need question to be in the template context. That means your view should look something like:
def view_question(request):
question = Question.objects.get(text="What is your name?")
return render(request, "template.html", {'question': question})
The error message with keyword arguments '{'username': ''}' suggests that question is missing from the template context.
When I first saw your url tag, I wondered if you were trying to loop through all the questions in a queryset, for example:
{% for question in question_loop %}
{% url 'questions:for_user' username=question.user.username %}
{% endfor %}
That's why I asked whether the url tag was in a loop.
Now that you've expanded your question, it sounds like you want the username of the logged in user. The auth context processor adds user to the template context, so you can use user.username to get the username.
{% url 'questions:for_user' username=user.username %}
However, your base template should probably handle users that are not logged in as well. You can add an if statement to avoid errors for anonymous users.
{% if user.is_authenticated %}
{% url 'questions:for_user' username=user.username %}
{% endif %}
Related
Please let me know that where i am making mistake?
views.py
class AddComment(LoginRequiredMixin, CreateView):
model = Comment
form_class = CommentForm
template_name = 'comment.html'
success_url = reverse_lazy('home')
def form_valid(self, form):
form.instance.name = self.request.user
form.instance.post_id = self.kwargs\['pk'\]
return super().form_valid(form)
Are these forms written correctly?
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('body', )
widgets = {
# 'name': forms.TextInput(attrs={'class': 'form-control'}),
'body': forms.Textarea(attrs={'class': 'form-control'}),
}
Should I make any changes in models?
models.py
class Comment(models.Model):
post = models.ForeignKey(Post,
related_name='comments',
on_delete=models.CASCADE)
name = models.ForeignKey(
User,
on_delete=models.CASCADE,
)
body = models.TextField(max_length=240)
date_added = models.DateTimeField(auto_now_add=True)
def __str__(self):
return '%s - %s' % (self.post.title, self.name)
This is comment section for letting user to comment on post with showing its own name?
comments.html
{% if not object.comments.all %}
<p>No comments yet...</p>
Add one
{% else %}
Add Comment
<br><br>
{% for comment in object.comments.all %}
<strong>{{ comment.name }} </strong> - <small>{{ comment.date_added }}</small>
<br>
{{ comment.body }}
<br><br>
<hr>
{% endfor %}
{% endif %}
Here is the urls of AddComment class view.
urls.py
path('post/<int:pk>/comment/', AddComment.as_view(), name='comment'),][1]
You did not state clearly what has gone wrong with your code. I would like to give some suggestions. First of all,
{% for comment in object.comments.all %}
...
{% endfor %}
You are putting this block of code inside {% if not object.comments.all %}...{% endif %} so it will not show on template if the comment section is not empty.
Also, this link:
Add Comment
should open a Django template form, where user can actually fill in the comment. After that, on POST request of the form, it will send comment data to the URL you put in action param of the form, as below:
<form action="{% url 'comment' post.pk %}" method="post">
[Comment code here]
</form>
which will link to this URL you provided:
path('post/<int:pk>/comment/', AddComment.as_view(), name='comment'),]
It will be better if you can provide your code in views.py as well to make it easier to track down where it goes wrong.
I want to display all the users, in my template but I cannot. I think there is a mistake in my codes but I cannot find it. Here is codes.
views.py
class UsersView(TemplateView):
template_name = 'users.html'
def get_context_data(self, **kwargs):
context = super(UsersView, self).get_context_data(**kwargs)
context['object_list'] = UserList.objects.all()
return context
models.py
class UserList(AbstractBaseUser):
first_name = models.CharField(max_length=200, blank=True, help_text="The first name of the user.")
last_name = models.CharField(max_length=200, blank=True, help_text="The last name of the user.")
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
help_text="The email and username of the user. Required."
)
users.html
{% extends 'blog/base.html' %}
{% block content %}
<h1>Users:</h1>
<ul>
{% for users in object_list %}
<li class="user">{{ user }}</li>
{% endfor %}
</ul>
{% endblock %}
And this is the page that I get:
Where is my mistake? Thank you.
Your code includes the following:
{% for users in object_list %}
<li class="user">{{ user }}</li>
{% endfor %}
The trouble with this is that the user template variable is not defined. Change users to user in the loop header and you should be OK.
You can use django.contrib.auth.models.User on your view with request.user.get_username() with this you use a standard user with Django. If go go admin URL you see user default.
For call in template :
{{ user.get_username }}
I have a delete view with 2 conditions "post" and "user".
The user requirement is fulfilled by self.object.user = self.request.user and post requirement is fulfilled by slug = self.kwargs['slug'](I think this may be the culprit)
Are my views correct?
I am new to python please forgive any silly mistakes.
Views.py
class ProofDelete(LoginRequiredMixin, DeleteView):
model = Proof
def delete(self, *args, **kwargs):
return super().delete(*args, **kwargs)
def get_success_url(self, *args, **kwargs):
slug = self.kwargs['slug']
print(slug)
obj = get_object_or_404(Post, slug=slug)
url_ = obj.get_absolute_url()
user = self.request.user
if user.is_authenticated():
if user in obj.made.all():
obj.made.remove(user)
else:
obj.made.add(user)
return url_
models.py
User = get_user_model()
class Proof(models.Model):
user = models.ForeignKey(User, related_name='proofmade')
post = models.ForeignKey(Post, related_name='proofmade')
made_at = models.DateTimeField(auto_now=True)
image_of_proof= models.ImageField()
proof_ = models.ImageField()
suggestions = models.TextField(max_length=1000)
def __str__(self):
return self.post.title
urls.py
app_name = 'proof'
urlpatterns = [
url(r'^new_proof/(?P<slug>[-\w]+)/$', views.ProofCreate.as_view(), name='new_proof'),
url(r'^proof_delete/(?P<pk>\d+)/$', views.ProofDelete.as_view(),name='proof_delete'),
also tried
url (r'^proof_delete/(?P<slug>[-\w]+)/(?P<pk>\d+)/$', views.ProofDelete.as_view(), name='proof_delete'),
I get the below error. Indicating error in the views
Error Message Click to see Error message
Same error message after scrolling down. Click to open
The answer was in the templates. Adding a forloop after the "if" statement solved the issue. Doing this handles both arguments of the Url. "slug" of "post" model and "pk" of the "proof" model. Without the forloop It was almost impossible to satisfy both arguments of the URL
The correct Url thanks to "Paulo Almeida"
url (r'^proof_delete/(?P<slug>[-\w]+)/(?P<pk>\d+)/$', views.ProofDelete.as_view(), name='proof_delete')
Below is the template
{% if user in post.made.all %}
{% for proof in user.proofmade.all %}
<a href="{% url 'proof:proof_delete' slug=post.slug pk=proof.pk %}">
<img src="{% static 'images/thumbs_up_RED.png' %}" height="25px">
</a><br/>
{% endfor %}
{% else %}
<a href="{% url 'proof:new_proof' slug=post.slug %}">
<img src="{% static 'images/thumbs_up_BLANK.png' %}" height="25px">
</a><br/>
{% endif %}
First, I have to say that is this my first application in Django. So my knowledge is still limited.
I have this home page where it shows all the data in my model. The model name is "Asset".
I am trying to have a search field inside the home page.
models.py
class Asset(models.Model):
asset_desc = models.CharField(max_length=120, null=False)
BEIRUT = 'Beirut'
SAIDA = 'Saida'
HALBA = "Halba"
base_choice = ((SAIDA, "Saida"), (BEIRUT, "Beirut"), (HALBA, "Halba"))
asset_base = models.CharField(max_length=120, null=False, choices=base_choice)
created_date = models.DateField(auto_now_add=True)
update_date = models.DateTimeField(auto_now=True)
asset_user = models.CharField(max_length=120, blank=True)
slug = models.SlugField()
def save(self, *args, **kwargs):
self.slug = slugify(self.asset_desc)
super(Asset, self).save(*args, **kwargs)
def __str__(self):
return self.asset_desc
views.py
def search_asset(request):
if 'q' in request.GET and request.GET['q']:
q = request.GET['q']
assets = Asset.objects.filter(asset_desc__icontains=q)
context = {'desc': assets}
return render(request, 'home.html', context)
html for the search field:
<form method="GET" class="navbar-form navbar-right">
<input type="text" class="form-control" placeholder="Search..."id="search_box" name="q">
urls.py
url(r'^search/$', "asset.views.search_asset", name="home")
Please any help on why it is not showing the result. I am using Django 1.9.
some corrections:
you dont need null=False for TextField() and CharField(), since they never save Null to database but empty string. so you can remove null=False
the search url name is home which logically not really approriate. it should be changed to search or search_view and then you can refer to it via url tag:
action="{% url 'search' %}"
this is useful if someone should look over your code. "Readability counts" ;)
and finally, put this to your home.html (actually you must already have it)
{% for asset in desc %}
<div>
{{ asset.asset_desc }} <br>
{{ asset.base_choice }} <br>
{{ asset.asset_user }}
</div>
{% endfor %}
I hope, this helps
You have not provided the template or the HTML portion where you list the results. You should consider the name of you context variable, but by following your name, you should list the results like this:
{% for asset in desc %}
<div>
{{ asset }}
</div>
{% endfor %}
Anything else looks correct.
Hope it helps
So my problem is that when I try to query to the image url so it can be posted to its corresponding Post all the images that have been uploaded to the media folder is being rendered, even though in the admin panel it shows that each post has it's own image and they are assigned to different posts, instead all of them are being rendered together for each and every post.
The models that I have are SellPost which is for creating a post and SellPostImage is for assigning the image to the post.
models.py
class SellPost(models.Model):
user = models.ForeignKey(User)
title = models.CharField(max_length=128)
category = models.ForeignKey(Category)
type = models.ForeignKey(SellPostType, default=None)
body = models.CharField(max_length=400)
price = models.DecimalField(decimal_places=1, max_digits=5, default=0.0)
views = models.IntegerField(default=0)
likes = models.IntegerField(default=0)
slug = models.SlugField(unique=True, default='automatic')
def save(self, *args, **kwargs):
self.slug = slugify(self.title)
super(SellPost, self).save(*args, **kwargs)
def __unicode__(self):
return self.title
class SellPostImage(models.Model):
user = models.ForeignKey(User, null=True)
post = models.ForeignKey(SellPost)
pictures = models.ImageField(upload_to='post_images', blank=True)
def __str__(self):
return "{}".format(self.post)
class Meta:
verbose_name_plural = "Post Images"
In the view I tried to create a context dict (because I'm a newbie in Django and have learned that from Tango with Django so I went with it) for the post and then the images:
views.py
def post(request, post_name_slug):
context_dict = {}
try:
post = SellPost.objects.get(slug=post_name_slug)
context_dict['post'] = post
post_image = SellPostImage.objects.all()
context_dict['post_image'] = post_image
except SellPost.DoesNotExist:
pass
return render(request, 'p.html', context_dict)
and here is how I tried to render them in the HTML file.
p.html
<ul>
{% for post in posts %}
<li>{{ post.title }} </li>
{% for post_images in post_image %}
<img style="width:200px; height:200px;" src="{{ post_images.pictures.url }}" />
{% endfor %}
{% endfor %}
</ul>
You'll want to filter the SellPostImage for the retrieved post:
post = SellPost.objects.get(slug=post_name_slug)
context_dict['post'] = post
post_image = SellPostImage.objects.filter(post=post)
context_dict['post_image'] = post_image
But you can just as easily put that logic part directly into your template:
{% for post in posts %}
<li>{{ post.title }} </li>
{% for post_images in post.sellpostimage_set.all %}
<img style="width:200px; height:200px;" src="{{ post_images.pictures.url }}" />
{% endfor %}
{% endfor %}
and then you can remove the SellPostImage in your views:
try:
post = SellPost.objects.get(slug=post_name_slug)
context_dict['post'] = post
except SellPost.DoesNotExist:
pass
In your post method you query for all SellPostImages:
post_image = SellPostImage.objects.all()
That's why you get all images for each post.
You can filter only the images associated with a post by doing the following instead:
post_image = SellPostImage.objects.filter(post=post)
It will provide all images for that specific post.