problems with an edit form/view - python

I work with Django 1.9. I created a view to add a new object and it works, but when to create a view to edit the objects, I have two different problems:
when I want to edit an album I click the link to the page where I want to see the entire list of albums for editing, but I get the error Exception Type: NameError and Exception Value: name 'album' is not defined that relates -> views.py in mod_artist form = AlbumForm(instance=album)
instead, when I want to edit an artist, I do the same thing as before to see the whole list of artists to be able to edit, but I get the error Exception Type:
UnboundLocalError and Exception Value: local variable 'artist' referenced before assignment that relates -> views.py in mod_artist form = ArtistForm(instance=artist)
my views.py file is
from django.shortcuts import render, redirect, get_object_or_404
from .forms import *
from .models import *
def mod_album(request):
if request.method == "POST":
form = AlbumForm(request.POST, instance=album)
if form.is_valid():
post = form.save(commit=False)
post.author = request.user
post.save()
return redirect('http://127.0.0.1:8000/')
else:
form = AlbumForm(instance=album)
return render(request,'polls/mod_album.html',{'form':form})
def mod_artist(request):
if request.method == 'POST':
form = ArtistForm(request.POST, instance=artist)
if form.is_valid():
artist = form.save(commit=False)
artist.author = request.user
artist.save()
return redirect('http://127.0.0.1:8000/')
else:
form = ArtistForm(instance=artist)
return render(request,'polls/mod_artist.html',{'form':form})
my index.html file is
...
<body>
<div class="container-fluid">
<div class="header">
<div>
<h1>personal library</h1>
</div>
<div id="wrap-nav">
<nav class="navbar navbar-inverse">
<div class="container-fluid">
<div class="collapse navbar-collapse" id="myNavbar">
<ul class="nav navbar-nav">
<li class="active">+ add album</li>
<li class="active">- edit album</li>
<li class="active">+ add artist</li>
<li class="active">- edit artist</li>
<li class="active">view the list of albums</li>
</ul>
</div>
</div>
</nav>
</div>
</div>
<div class="row">
<div class="col-xs-12 col-sm-6 col-md-6">
{% for album in albums %}
<ul>
<li>Album name: {{album.name}}</li>
<li>Artist: {{album.artist}}</li>
<li>Genre: {{album.genre}}</li>
<li>Songs: , </li>
<li>Vote: {{album.vote}}</li>
</ul>
<hr />
{% endfor %}
</div>
<div class="col-xs-6 col-md-6">
{% for artist in artists %}
<ul>
<li>Artist name: {{artist.name}}</li>
</ul>
<hr />
{% endfor %}
</div>
</div>
</div>
</body>
...
my urls.py file is
from django.conf.urls import url
from . import views
urlpatterns=[
...
url(r'^new_album/$', views.new_album, name='new_album'),
url(r'^mod_album/$', views.mod_album, name='mod_album'),
url(r'^new_artist/$', views.new_artist, name='new_artist'),
url(r'^mod_artist/$', views.mod_artist, name='mod_artist'),
]
and my forms.py file is
from django import forms
from .models import *
class AlbumForm(forms.ModelForm):
class Meta:
model = Album
fields = ['name','artist','year','genre','vote']
class ArtistForm(forms.ModelForm):
class Meta:
model = Artist
fields = ['name']
thanks in advance of our time.

Related

Field 'id' expected a number but got 'xyz'

In Models.py
class Post(models.Model):
user = models.CharField(max_length=100)
likes = models.IntegerField(default=0)
content = models.TextField()
date = models.DateTimeField(auto_now_add=True)
class Profile(models.Model):
following = models.ForeignKey('User',on_delete=models.CASCADE,related_name='following')
user = models.ForeignKey('User',on_delete=models.CASCADE,related_name='user')
def __str__(self):
return self.user
In views.py
def viewProfile(request,username):
posts = Post.objects.filter(user=username).order_by('id').reverse()
profile = Profile.objects.filter(user=username)
no_of_followers = profile.following.count()
return render(request, "network/profile.html",{
"posts":posts,
"username":username,
"no_of_followers":no_of_followers
})
In profile.html
{% extends "network/layout.html" %}
{% block body %}
<h2 style="margin-left: 20px;">Posts of {{username}}</h2>
<div class="col-sm-6">
<div class="card">
<div class="card-body">
<h5 class="card-title">Profile Details</h5>
<p class="card-text">Followers:{{no_of_followers}}</p>
<p class="card-text">Followings:0</p>
Go somewhere
</div>
</div>
</div>
{% for post in posts %}
<div class="card" style="width:70%;margin-left: 10%;margin-right: 20%;">
<div class="card-body">
<h5 class="card-title">{{post.user}}</h5>
<div class="form-group">
<p>{{post.date}}<br>{{post.content}}</p>
</div>
<p>{{post.likes}}</p>
</div>
</div>
{% endfor %}
{% endblock %}
Facing an error of Field 'id' expected a number but got 'xyz'. xyz is the username
If I replace profile = Profile.objects.filter(user=username)with profile = Profile.objects.filter(user__user=username) then I am getting the error django.core.exceptions.FieldError: Related Field got invalid lookup: user
The lookup should be:
profile = Profile.objects.get(user__username=username)
since you want to retrieve a Profile for which the user has a username that has the given username.
You probably should use .get(…) [Django-doc] here to retrieve a Profile object, not a QuerySet of Profiles.
You might want to use the get_object_or_404(…) function [Django-doc] instead, such that it returns a 404 in case no such profile exists:
from django.shortcuts import get_object_or_404
def viewProfile(request,username):
posts = Post.objects.filter(user__username=username).order_by('-id')
profile = get_object_or_404(Profile, user__username=username)
no_of_followers = profile.following.count()
return render(request, 'network/profile.html',{
'posts':posts,
'username':username,
'no_of_followers":no_of_followers
})

Redirected to same page after POST method django

I am creating this project in django. I am working on reporting films, where I go to a film-detail view, then hit the report button. A report_form shows up where I justify why I am reporting, and then I click report. Everything works fine, but there is one thing. After reporting I get sent back to a random(?) film-detail view, but I would like to go back to the view for the film I am reporting. But how???
views.py
class FilmReportView(LoginRequiredMixin, CreateView):
model = Report
fields = ['reason']
def form_valid(self, form):
form.instance.reporter = self.request.user
form.instance.reports_id = self.kwargs['pk']
return super().form_valid(form)
def get_success_url(self):
return "film/<int:pk>/report"
report_form.html
{% extends "board/base.html" %}
{% load crispy_forms_tags %}
{% load materializecss %}
{% block content %}
<div class="valign-wrapper row login-box">
<div class="col card hoverable s10 pull-s1 m6 pull-m3 l8 pull-l2">
<form method="POST" action="" enctype="multipart/form-data">
{% csrf_token %}
<div class="card-content">
<span class="card-title">Jusity why you want to report this film?</span>
<div class="row">
{{ form|materializecss }}
</div>
</div>
<div class="card-action right-align">
<input type="reset" id="reset" class="btn-flat grey-text waves-effect">
<input type="submit" class="btn green waves-effect waves-light" value="Report">
</div>
</form>
</div>
</div>
{% endblock content %}
urls.py
urlpatterns = [
path("", views.films_view, name="board-home"),
path("film/add", FilmAddView.as_view(), name="film-add"),
path("film/<int:pk>/", FilmDetailView.as_view(), name="film-detail"),
path("film/<int:pk>/report", FilmReportView.as_view(), name="film-report"),
]
models.py
class Report(models.Model):
reason = models.TextField()
reporter = models.ForeignKey(User, on_delete=models.CASCADE, related_name="Reporter")
reports = models.ForeignKey(Film, on_delete=models.CASCADE)
def __str__(self): # pragma: no cover
return f"{self.reports.title} reported by {self.reporter.username}"
def get_absolute_url(self): # pragma: no cover
return reverse("film-detail", kwargs={"pk": self.pk})
Fix your FilmReportView get_success_url() to look like that:
def get_success_url(self):
return reverse("film-detail", kwargs={"pk": self.object.reports.id})
That should take care of it
In your views.py or even in the template you can put next parameter with url you want:
form/action/url?next={{request.path}}
See more about next:
https://www.reddit.com/r/django/comments/32s9ag/how_do_i_set_the_next_context_variable_in_django/

Associate multiple unique forms to a unique object in Django

I'm trying to build a web application using Django where a user can create a 'Project' and within that 'Project', there are four different forms.
My Question is, how do I associate those forms to a specific 'project' in the sense that the form is linked to that specific 'project'.
I'm close to doing it but I'm having issues with the 'create-project.html', 'create-request-1.html' and 'create-request-2.html' pages from rendering due to the 'PK' in the 'projects.html' page URL.
The exact errors I get for navigating to those pages is -
NoReverseMatch at /projects/create-project/
Reverse for 'initiate_project' with no arguments not found. 1 pattern(s) tried: ['projects\\/project\\/(?P<pk>[0-9]+)\\/$']
Or
NoReverseMatch at /project/create-post-1/
Reverse for 'initiate_project' with no arguments not found. 1 pattern(s) tried: ['projects\\/project\\/(?P<pk>[0-9]+)\\/$']
The path is as follows -
'projects.html' -
'create-project.html' -
'initiate-project.html' -
'create-request-1.html'
'create-request-2.html'
I can navigate and go into each unique 'project' (e.g. project 1, project 2) in 'projects.html' but I can't get into my forms ('create-request-1.html', 'create-request-2.html') inside the 'initiate-project.html' page that's within each 'project' in the 'projects.html' page.
Here's my code so far -
model.py -
from django.db import models
class create_new_project(models.Model):
list_display = ('project_name', 'project_manager',
'technical_lead', 'test_lead')
class Meta:
verbose_name = 'Create New Project'
verbose_name_plural = 'Create New Projects'
project_name = models.CharField(max_length=100)
project_manager = models.CharField(max_length=100)
technical_lead = models.CharField(max_length=100)
test_lead = models.CharField(max_length=100)
environment_choices = (
('1', '1'),
('2', '2'),
('3', '3')
)
environment = models.CharField(
max_length=50, choices=environment_choices, default='ICCS')
def __str__(self):
return self.project_name
views.py
from django.shortcuts import render
from django.shortcuts import render, get_object_or_404
from main.models import *
# Create your views here.
def index(request):
return render(request, 'main/index.html')
def projects(request):
CreateNewProject = create_new_project.objects.all()
args = {'CreateNewProject': CreateNewProject}
return render(request, 'main/projects.html', args)
def create_project(request):
return render(request, 'main/create-project.html')
def initiate_project(request, pk):
InitiateProjectURL = get_object_or_404(create_new_project, pk=pk)
return render(request, 'main/initiate-project.html', {'InitiateProjectURL': InitiateProjectURL})
def create_post_request_1(request):
return render(request, 'main/create-post-request-1.html')
def create_post_section_2(request):
return render(request, 'main/create-post-request-2.html')
urls.py
from django.urls import include, path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('projects/', views.projects, name='projects'),
path('projects/create-project/', views.create_project, name='create_project'),
path('projects/project/<int:pk>/',
views.initiate_project, name='initiate_project'),
path('project/create-post-request-1/',
views.create_post_request_1, name='create_post_paid_request_section_1'),
path('project/create-post-request-2/',
views.create_post_request_2, name='create_post_request_2'),
]
projects.html
<div class="row">
<a href="{% url 'create_project' %}" class="card card-1 bg-red shadow m-2">
<div class="card-body d-flex h-100">
<div class="text-center mx-auto justify-content-center align-self-center">
{% load staticfiles %}
<img src="{% static 'main/images/plus.svg' %}" alt="Plus Icon" height="60vh">
<div class="mb-3 pt-4 text-white">Create New Project</div>
</div>
</div>
</a>
{% for create_new_project in CreateNewProject %}
<div class="card card-1 bg-white shadow m-2">
<div class="card-body">
<h4 class="card-title text-red">{{ create_new_project.project_name }}</h4>
<div class="card-text pt-2 pb-2">
<div class="mb-3"><b>Project Manager: </b>{{ create_new_project.project_name }}</div>
<div class="mb-3"><b>Project Lead: </b>{{ create_new_project.project_manager }}</div>
<div class="mb-3"><b>Test Lead: </b>{{ create_new_project.test_lead }}</div>
<div class="mb-3"><b>Environment: </b>{{ create_new_project.environment }}</div>
</div>
<div class="float-right">
<a href="{% url 'initiate_project' pk=create_new_project.pk %}" class="text-red">
{% load staticfiles %}
<img src="{% static 'main/images/next.svg' %}" class="text-red" alt="Next Icon" height="25vh"></a>
</div>
</div>
</div>
{% endfor %}
</div>
create-post-request-1.html / create-post-request-2.html
<div class="col-md-2">
Cancel
</div>
To better illustrate what I'm trying to do, See the following image - Visual description
the href for the a tag in create-post-request-1.html / create-post-request-2.html should be sth like "{% url 'initiate_project' pk=any_pk_you_choose %}" instead of {% url 'initiate_project' %}

Django: New Data from Database won't show in a URL redirect until I click the link again

My problem is that when the user creates a new record on the database in my webpage (Mysql) and the system redirects the user to the list of elements created, the new element won't show up until I click again the link option on a section. In other words I want django to show the new results when I redirect the user to the list, here's some fragments of code I'm using:
This is the link where the user clicks to show the list after creating a new object:
<div class="modal-footer">
<div class="col-lg-12 text-right">
Regresar a Listado
</div>
</div>
This is the list where I show the elements from the database:
{% for portal in portal_list %}
<section class="search-result-item">
<a class="image-link" href="/microsite/myportal/view/{{portal.portal_id}}">
<img class="image" src="{% static 'img/template-icon.png' %}">
</a>
<div class="search-result-item-body">
<div class="row">
<div class="col-sm-9">
<h4 class="search-result-item-heading">
No. de Plantilla : {{portal.portal_id}}
</h4>
<p class="description">
ID Terminos: {{portal.terms_id}}
</p>
</div>
<div class="col-sm-3 text-align-center">
<p class="value3 text-gray-dark mt-sm">
{{ randomNumber|random }} visitas
</p>
<p class="fs-mini text-muted">
Por Semana
</p>
<br>
Ver Detalles
</div>
</div>
</div>
</section>
{% endfor %}
Here's my function in views: (The object that comes from MySQL is called myportal_list)
from django.shortcuts import render
from django.http import HttpResponseRedirect
def myportal_list(request, device_serial):
logger.debug("views - myportal_create")
deviceObject = CaptivePortalService.CaptivePortalService().getNetwork(device_serial)
captive_portal_list=""
context = {'device_object': deviceObject}
myportal_list = my_portal.objects.all()
context['portal_list'] = myportal_list
number = []
for i in myportal_list:
number.append(randint(0, 25))
context['randomNumber'] = number
return render(request, URL_MYPORTAL_LIST, context)
And finally there's my list of options, that is actually the only way to show the new data from the database: (even if i press F5 the new data wont show)
<ul id="network-option" class="panel-collapse collapse ">
<li class="">Mi Portal</li>
<!-- <li class="">Configuraciones de Accceso</li> -->
<li class="">Configuraciones de Accceso</li>
<li class="">Promociones</li>
<li class="">Términos de Uso</li>
</ul>
The view function where I create a new record: (Im handling the response with AJAX to be able to handle messages if there's an error or if the form was submitted correctly, in this case the messages are listed in the modal footer that I posted first)
def myportal_create(request, device_serial):
if request.method == "GET":
logger.debug("views - myportal_create")
deviceObject = CaptivePortalService.CaptivePortalService().getNetwork(device_serial)
captive_portal_list=""
context = {'device_object': deviceObject}
promotion_list = promotions.objects.all()
context['promo_list'] = promotion_list
terms_list = use_terms.objects.all()
context['terms_list'] = terms_list
return render(request, URL_MYPORTAL_CREATE, context)
if request.method == "POST":
form = PortalForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect("/microsite/myportal/list/"+ device_serial)
else:
print(form.errors)
Also I have the correct configuration to use MySQL on settings so I don't think that being the problem.
Thanks for the time.

Django form not rendering properly

I am following the documentation of the Django Forms but I do not know why my form does not want to show up !
I am creating a form that will get an email en create invitation for user to sign in using this app :https://github.com/bee-keeper/django-invitations
My forms.py:
class InviteForm(forms.Form):
email1 = forms.EmailField(label='Email 1')
My Views.py:
from django.shortcuts import render
from django.views.generic import TemplateView
from .forms import InviteForm
class candidateIndex(TemplateView):
template_name= 'candidateIndex.html'
class HRIndex(TemplateView):
template_name= 'HRindex.html'
def create_invite(request):
if request.method == 'POST':
form = InviteForm(request.POST)
if form.is_valid:
email = form.cleaned_data['email1']
invite = Invitation.create('form.email1')
invite.send_invitation(request)
print("The mail was went")
else:
print("Your form is not valid")
else:
form = InviteForm()
return render(request, 'HRindex.html', {'form': form})
My HTML:
{% extends 'base.html' %}
{% block body %}
<div class="jumbotron">
<h1>Welcome to SoftScores.com</h1>
<h2>Team analytics platfom</h2>
<h3>Welcome to {{user.username}}, it is your Page</h3>
</div>
<div class="container">
<p>
<a class="btn btn-primary" data-toggle="collapse" href="#collapseExample" aria-expanded="false" aria-controls="collapseExample">
Create a new team
</a>
</p>
<div class="collapse" id="collapseExample">
<div class="card card-body">
In order to create a new team please invite new members. A link will be sent to them in order to give the access to the application
</div>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
</div>
</div>
urls.py:
from django.conf.urls import url
from website import views
app_name = 'website'
urlpatterns = [
url(r'^candidateIndex/$', views.candidateIndex.as_view(), name='candidate_index'),
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
]
When it render the page I get only the button but the form does not seems to work
Do you habe any idea ?
You HR_index url is being handled by the HRIndex view, but this does not have any code to handle the form.
url(r'^HRIndex/$', views.HRIndex.as_view(), name='HR_index'),
Since a TemplateView is not really suited to handling a form, it would be better to modify the URL pattern to use the create_invite view instead:
url(r'^HRIndex/$', views.create_invite, name='HR_index'),

Categories