Authenticated user post DJANGO, save form - django

I am creating an app where user can search for recipes by ingredients. I want that logged in user can add recipe by himself. I have created form where i am using ModelForm. Now i want to do that after user push submit recipe will be added/saved to recipes which i can see in admin panel and also it will be possible to search for it, but now it looks like it is impossible to save the new recipe...
My code in view:
def add_recipe(request):
if not request.user.is_authenticated:
return redirect('login_required')
add_recipe = RecipeForm(request.POST or None)
if add_recipe.is_valid():
print("your recipe has been added!")
add_recipe.save()
template = "drinks/add_recipe.html"
return render(request, template, {'RecipeForm': add_recipe})
My form:
from django.forms import ModelForm
from drinks.models import Recipe
class RecipeForm(ModelForm):
class Meta:
model = Recipe
fields = ['recipe_name', 'preparation', 'ingredients']
My templates add_recipe:
<form method="post" action="">
{% csrf_token %}
<table>
{{RecipeForm}}
</table>
<input type="submit" value="Add recipe"/>
</form>
my urls:
urlpatterns = [
path('', views.drink_list, name='drink_list'),
path('search/', views.search_results, name='search_results'),
path('no_name/', views.drink_list, name='drink_list'),
path('signup/', views.signup, name='signup'),
path('add_recipe/', views.add_recipe, name='add_recipe'),
path('login_required/', views.login_required, name='login_required'),
]

I am not sure what you are trying to do with your views (their names are not very explicit), but have you registered the view through your urls.py file?
Also, action="" in your template won't do anything. You need to specify the url to send your post request! action should not be equaled to "", but to the url you want to submit your form. In your case, you should have action="{% url 'add_recipe' %}"

Related

passing a value in anchor tag in django

So I'm in my profile page & want to edit my profile so I click edit button ,it takes me to a edit page where I have two buttons 'save'(inside form tag) & 'Exit'. Now if I click exit I want to get redirected to profile page of same person again. what input should I pass in below tag to do this?
(<button>Exit</button>
adding urls.py
urlpatterns = [
path('',views.home, name='home'),
path('login/',views.loginp, name='login'),
path('profile/<str:ck>/',views.profile, name='profile'),
path('Edit_profile/<str:ck>/',views.Edit, name='Edit'),
path('logout/',views.logoutp, name='logout'),
path('register/',views.register, name='register'),
]
page where my button is located
<form method="POST">
{% csrf_token %}
{{form.as_p}}
<input type ="submit" value="Save">
</form>
<button>Exit</button>
For going back to particular profile you will need a url with profile/int:id and have to pass unique id of that particular profile in your url while calling exit.
Below is the sample you can do it where profile.id contains value of id of a profile.
<button>Exit</button>
i am not agree with other answers.
If you on your profile page, it means you are logged in.
In this case - you don't need to define user.pk, and it is better for usability - i can simply save the link mydomain/profile instead of mydomain/profile/user_pk.
But you should define, how you get an user from Request.
class ProfileView(LoginRequiredMixin, DetailView):
model = User
def get_object(self, *args, **kwargs):
self.kwargs['pk'] = self.request.user.pk
return super().get_object(*args, **kwargs)
I am shure - this is the better solution, than send pk in url.
LoginRequiredMixin- default django mixin for GCBV
DeteilView - django GCBV
More here:
https://docs.djangoproject.com/en/4.1/topics/auth/default/#django.contrib.auth.mixins.LoginRequiredMixin
and
https://docs.djangoproject.com/en/4.1/ref/class-based-views/generic-display/#detailview

Login Required Mixin acting up on a view where i didn't even include it(django)

So, i want my website's content only to be visible to the registered users, so i have put "LoginRequiredMixin" amd "#login_required" tags on most of my views except login and register views. Now, for registration, i want to give the registrants a choice before registering (whether they are current university students or alumni/recent graduates), this is how i am doing this:
class choice(View):
template = "network/choice.html"
def get(self, request):
form = ChoiceForm()
return render(request, self.template, {
"form": form,
"message": "Are you a curent student or an alumni/about to graduate"
})
def post(self, request):
form = ChoiceForm(request.POST)
if form.is_valid():
current = form.cleaned_data["current"]
if current:
return HttpResponseRedirect('accounts/register/current')
else:
return HttpResponseRedirect('accounts/register/alum')
where ChoiceForm just contains a boolean field, and "register/str:type" is my registration URL.
But after i submit the Choice Form:
<form action="{% url 'network:choice' %}" method="post">
{% csrf_token %}
{{ form|crispy }}
<br>
<input type="submit" value="Proceed"
</form>
the url to which i am taken to is:
/accounts/login/?next=/register/current
(i have not included any authentication check on the registration view, that won't make any sense lol)
Where i might have gone wrong is:
because i want anyone truing to access a restricted page to be redirected to the login page, i have defined my Urlpattern as follows:
path('accounts/login/', views.login_view.as_view(), name="login_view"),
path('accounts/register/<str:type>', views.register.as_view(), name="register"),
where 'accounts/login' is the path which django redirects to with the login_required tag. Did i do something wrong here?
This is my register view, although i am pretty sure that's not where the problem is as this view isn't even loading up even if i type in the url 'register/current'. I am still being redirected to accounts/login/?next=/register/current
Urlpatterns:
path('', views.index, name='index'),
path('new/<str:type>', views.new_page.as_view(), name="new"),
path('<str:type>/<str:name>', views.page.as_view(), name="page"),
path('logout', views.logout_view, name="logout_view"),
path('accounts/login/', views.login_view.as_view(), name="login_view"),
path('accounts/register/<str:type>', views.register.as_view(), name="register"),
path('choice', views.choice.as_view(), name="choice"),

django, views direct to a another html page

I am using Django for develop a website. The website is intended to use to search information stored in a MySQL database.
This is the current basic flow of the web site.
1) index.html - this has a form to select an option
2) according the option, users will redirect to search.html (include a form)
3) once the user provides the criteria, the result will be displayed in reply.html
In my views.py , I have two functions.
from django.shortcuts import render
from website.models import WebsiteRepository
from .forms import SearchForm
from .forms import SelectTypeForm
def Search(request):
if request.method == 'POST':
#do something
return render(request, 'reply.html', {'env_dict':env_dict})
else:
#do something
return render(request, 'search.html', context = context)
def index(request):
if request.method =='POST':
#do something
return render(request, 'search.html', context = context)
else:
#do something
return render(request, 'index.html', context= context)
When I go to index.html page, I can select a option and it will direct me to search.html. After, I fill the form there and submit, it wont give me the reply.html page.
I have a feeling that, I could make this work by changing urls.py.
from django.urls import path
from website import views
urlpatterns = [
path('', views.index, name='index'),
#path('search/', view.Search, name ='Search')
]
I tried to google it. But its too much details and Iam kind of lost.
Do any of you guys know how to achieve this?
Thanks
search.html
{% extends "base_generic.html" %}
{% block content %}
<h3>Welcome to search information Repository</h3>
<form method="post">
{% csrf_token %}
{{form.as_p}}
<button type = 'submit'>submit</button>
</form>
{% endblock %}
index.html
{% block content %}
<h3>Welcome to information Repository</h3>
<form method="post">
{% csrf_token %}
{{form.as_p}}
<button type = 'submit'>submit</button>
</form>
just for clarify things more, ill add the forms.py too
from django import forms
from .models import WebsiteRepository
class SearchForm(forms.Form):
websiterepository = WebsiteRepository
env_indicators = websiterepository.objects.filter (key_aspect='Environmental').values_list('repo_id','indicator')
indicator = forms.ChoiceField(choices=env_indicators,label = 'Indicator' )
OPTIONS = (('2000','2000'),('2001','2001'),('2002','2002'), ('2003','2003'),('0000','0000'),)
year = forms.ChoiceField(choices=OPTIONS)
class SelectTypeForm(forms.Form):
OPTIONS = (('1', 'Envirnmental Indicators'),('2','Economic Indicators'),('3','Social Indicators'),)
types = forms.ChoiceField(choices=OPTIONS)
Your code is wrong on many points.
First thing first: for a search, you want a GET request, not a POST (POST is for updating the server's state - adding or updating your database mostly). This is the semantically correct method (since you want to GET data), and it will allow a user to bookmark the url.
Second point: you don't want to submit the search form to the index view but to the search view. No need for redirects etc, just use the {% url %} templatetag to fill the action attribute of your form (you of course need to have a 'Search' url in your urls.py):
<form method="get" action="{% url 'Search' %}">
{% csrf_token %}
{{form.as_p}}
<button type = 'submit'>submit</button>
</form>
if you want to have this form on more than one page (which is often the case for search forms), use an inclusion tag tha will take care of creating an unbound SearchForm and render the template fragment.
Then in your search view, you only want GET requests, and do not use two different templates, this will only lead to useless duplication.
def Search(request):
form = SearchForm(request.GET)
# use the form's data - if any - to get search results
# and put those results (even if empty) in you context
return render(request, 'reply.html', {'env_dict':env_dict})
And finally, your search form is totally broken:
class SearchForm(forms.Form):
# this is totally useless
websiterepository = WebsiteRepository
# this will only be evaluated once at process startup, so you will
# get stale data in production - and probably different data
# per process, in a totally unpredictable way.
# You need to either put this in the form's __init__ or wrap it
# in a callable and pass this callable
env_indicators = websiterepository.objects.filter (key_aspect='Environmental').values_list('repo_id','indicator')
indicator = forms.ChoiceField(choices=env_indicators,label = 'Indicator' )
# are you going to manually add a new year choice every year ???
OPTIONS = (('2000','2000'),('2001','2001'),('2002','2002'), ('2003','2003'),('0000','0000'),)
year = forms.ChoiceField(choices=OPTIONS)
For the "indicators" ChoiceField you want something like:
def get_indicators_choices():
return Websiterepository.objects.filter (key_aspect='Environmental').values_list('repo_id','indicator')
class SearchForm(forms.Form):
# IMPORTANT : we are NOT calling the function here, just
# passing it (python functions are objects) to the field, which
# will call it everytime the form is instanciated, so you don't
# have stale data
indicator = forms.ChoiceField(
choices=get_indicator_choices,
label='Indicator')
As a last note: be consistent with your namings (ie why name one view in all lower (index) and capitalize the other (Search) ? Whichever convention you choose (I strongly suggest respecting pep8 here), at least stick to it for the whole project.
The problem is that code is not redirecting to /search, instead rendering search.html after post from index.html.
Try doing like-
views.py-
#your code
def index(request):
#do something
if request.method == 'POST':
return redirect('Search')
else:
#render index.html
def search(request):
#do something
if request.method == 'POST':
#render reply.html
else:
#render search.html
Another way to achieve this is if you specify action in your form so that form posts on /search.
search.html
<form method="post" action="/search">
{% csrf_token %}
{{form.as_p}}
<button type = 'submit'>submit</button>
</form>

use success_url to go to root directory after submit form

I have a simple class based view (in an app video) that is creating an object using a form in a template (upload_video.html). When I submit the form, I just want to redirect to the home page, or the root index. It seems like this should be so easy. I am getting an error saying there is no page. I have tried several different ways of doing this, the code i have below is just one example.
views.py
class UploadVideo(CreateView):
model = Video
fields = ['title', 'description']
template_name = 'upload_video.html'
success_url = reverse_lazy('index.html')
upload_video.html
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Upload Video"/>
</form>
</body>
</html>
root.urls
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^$', index),
url(r'^video/', include('video.urls'))
Error
Page not found (404)
Request Method: GET
Request URL: http://127.0.0.1:8000/video/index.html
Using the URLconf defined in flash2.urls, Django tried these URL patterns, in this order:
^admin/
^$
^video/ ^upload [name='upload']
The current URL, video/index.html, didn't match any of these.
You need to pass urlname to the revers_lazy method, not the template name. Try to change in url.py:
url(r'^$', index, name="index")
And in UploadVideo class:
success_url = reverse_lazy('index')

Form fields not being displayed Django

I am still learning Django. I have been looking at various tutorials but I am struggling with forms on django framework.
The problem is that I am unable to display the form field for email on the base.html page. It is basically a subscription form. I am still new to django. This is what I have made till now.
models.py
from django.db import models
class SubscribeModel(models.Model):
email = models.CharField(max_length=100)
forms.py
from django import forms
from models import SubscribeModel
class SubscribeForm(forms.ModelForm):
class Meta:
model=SubscribeModel
views.py
def loadform(request):
form = SubscribeForm()
return render_to_response('base.html', {'form': form},context_instance=RequestContext(request))
base.html
<html>
...
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Subscribe"></ul>
</form>
...
</html>
urls.py
urlpatterns = patterns('',
url(r'^$', 'chsite.blog.views.index'),
url(r'^$', 'chsite.blog.views.loadform'),
url(r'^admin/', include(admin.site.urls)),
)
Once you are edited the question, I can see two url(---) reffenceced to the same url. Hence Django will loadd the first one. It means you never load the loadform view. So try removing the line:
url(r'^$', 'chsite.blog.views.index'),
or edit the actual tuple for the loadform for instance:
url(r'^suscribe/$', 'chsite.blog.views.loadform'),
and go to your browser at 127.0.0.1:8000/suscribe/ url.
You have to define different url patterns as your first two are identical. URL processing stops at first hit, in your case uses index view.