I'm trying to set up something using Django 1.11 and python for my job where it will display a list of projects submitted by the logged in user. The user can click on the Project name and it will take the user to that project to edit it if they need to. I have it showing the list of projects but when the user clicks the name I get an error. It works fine when there is only 1 project displaying for that users. The error and my code is below.
MultipleObjectsReturned at /edit/
get() returned more than one Project -- it returned 2!
Request Method: GET
Request URL: http://127.0.0.1:8000/edit/
Django Version: 1.11
Exception Type: MultipleObjectsReturned
Exception Value:
get() returned more than one Project -- it returned 2!
url.py
urlpatterns = [
url(r'^index/',views.Index.as_view(),name='index'),
url(r'^form/', views.Form.as_view(), name = 'form'),
url(r'^edit/', views.EditProject.as_view(), name = 'editProject'),
]
views.py
class Index(LoginRequiredMixin,ListView):
template_name = 'sitename/index.html'
form_class = IndexForm
def get_queryset(self):
return Project.objects.filter(user=self.request.user)
class EditProject(LoginRequiredMixin, UpdateView):
template_name = 'irbSite/form.html'
form_class = ProjectForm
success_url = reverse_lazy('irbSite:index')
# works only when there is 1 project object
def get_object(self):
return Project.objects.get(user=self.request.user)
index.html
{% if user.is_authenticated %}
{% if project_list %}
<tr>
<th>Project Number</th>
<th>Project Name</th>
<th>Is Complete</th>
<th>Is Approved</th>
</tr>
{% for project in project_list %}
<tr>
<td><a href="{% url 'irbSite:editProject'%}">{{project.project_id}}</td>
<td>{{project.project_name}}</a></td>
<td>{{project.is_complete}}</td>
<td>{{project.is_approved}}</td>
{% endfor %}
</tr>
{% else %}
<p>You dont have any current IRB forms. Select "Submit New Project" on the left to start one.<p>
use .filter to get multiple object while querying.
Ex:
def get_object(self):
return Project.objects.filter(user=self.request.user)
Related
My models.py:
class fields(models.Model):
name = models.CharField(max_length=18)
link = models.TextField()
The link contains the hyperlink of the related name.
My views.py:
def index(request):
listing = fields.objects.all()
context ={'listing':'listing'}
return render(request,'index.html',context)
urls.py
urlpatterns = [
path('admin/', admin.site.urls),
path('',index,name="index"),
]
template:
{% for i in listing %}
<tr>
<td data-label="name">{{ i.name }}</td>
<td data-label="Quote"><button>{{ i.link }}</button></td>
<tr>
{% endfor %}
This redirects to the hyperlink that is displayed in the template but I want to do some automation after it redirects into this link.
Now, I want to pass the context of this function which only includes the link to the other view function so that another view function will be:
def bypass_link(request):
# get the link from above function
# execute some selenium scripts in the link
The simple template to illustrate this will be:
{% for i in listing %}
<tr>
<td data-label="name">{{ i.name }}</td>
<td data-label="Quote"><button>{{ i.link }}</button></td>
<tr>
{% endfor %}
You can pass the id of the object into the url by altering the following:
template
<td data-label="Quote">
{{ i.link }}
</td>
urls.py
from django.conf.urls import url
url(r'^bypass_link/(?P<pk>\d+)/$', views.bypass_link, name="bypass_link"),
Then in your function you need to find the same model instance and then extract the link.
def bypass_link(request, pk=None):
instance = fields.objects.get(pk=pk)
print(instance.link) # now you have your link
Now you have access to the link via instance.link
You can pass variable to different views in Django using session
My example is using Django 3.2, be sure that sessions requirement are set in settings.py. But by the default config, the following example should work.
def index(request):
listing = fields.objects.all()
# The session object must be json serializable, pay attention
listing_list = [[list.name, list.i] for list in listing]
# set the session variable
request.session['listing_list'] = listing_list
context ={'listing':listing}
return render(request,'index.html',context)
def bypass_link(request):
# get the link from above function
# execute some selenium scripts in the link
# Got the session variable
listing_list = request.session.get('listing_list')
# Do what you want with it here
I'm new to Django and having a hard time figuring out how to get a model form to save to my db. I've been following some tutorials/books and spending a lot of time on SO and I just can't figure this piece out. The book examples i'm following is creating an IMDB type website where a user can vote movie quality (changed to games for my example).
python v. 3.6.7,
django v. 2.1.3,
postgres v. 2.2.2
Here is the model i'm trying to store and the associated manager
class VoteManager(models.Manager):
def get_vote_or_unsaved_blank_vote(self, game, user):
try:
vote = Vote.objects.get(game=game, user=user)
return vote
except self.model.DoesNotExist:
vote = Vote(game=game, user=user)
return vote
class Vote(models.Model):
objects = VoteManager()
value = models.FloatField()
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
game = models.ForeignKey(Game, on_delete=models.CASCADE,)
voted_on = models.DateTimeField(auto_now=True)
class Meta:
unique_together = ('user', 'game')
Now the model form I am trying using to try and store this
class VoteForm(forms.ModelForm):
user = forms.ModelChoiceField(widget=forms.HiddenInput, queryset=get_user_model().objects.all(), disabled=True)
game = forms.ModelChoiceField(widget=forms.HiddenInput, queryset=Game.objects.all(), disabled=True)
value = forms.FloatField()
class Meta:
model = Vote
fields = ('user', 'game', 'value')
Template i'm using to display this information.
{% block main %}
<h1>{{ object }}</h1>
<p class="lead">
{{ object.summary }}
</p>
{% endblock %}
{% block sidebar %}
{# rating div omitted #}
<div>
{% if vote_form %}
<form
method="post"
action="{{ vote_form_url }}" >
{% csrf_token %}
{{ vote_form.as_p }}
<button
class="btn btn-primary" >
Vote
</button >
</form >
<h3>Score: {{ object.score|default_if_none:"No score yet!" }}</h3>
{% else %}
<p >Log in to vote for this game</p >
{% endif %}
</div >
{% endblock %}
Finally the views to combine all of these pieces
class GameDetail(DetailView):
queryset = Game.objects.all_with_related_persons_and_score()
def post(self, request, *args, **kwargs):
return redirect('core:CreateVote', game_id=kwargs['pk'])
def get_context_data(self, **kwargs):
ctx = super().get_context_data(**kwargs)
if self.request.user.is_authenticated:
vote = Vote.objects.get_vote_or_unsaved_blank_vote(game=self.object, user=self.request.user)
if vote.id:
vote_form_url = reverse('core:UpdateVote', kwargs={'game_id': vote.game.id, 'pk': vote.id})
else:
vote_form_url = reverse('core:CreateVote', kwargs={'game_id': self.object.id})
ctx['vote_form'] = VoteForm(instance=vote)
ctx['vote_from_url'] = vote_form_url
return ctx
class CreateVote(LoginRequiredMixin, CreateView):
form_class = VoteForm
def get_initial(self):
initial = super().get_initial()
initial['user'] = self.request.user.id
initial['game'] = self.kwargs['game_id']
return initial
def get_success_url(self):
print('never called?')
game_id = self.kwargs['game_id']
return reverse('core:GameDetail', kwargs={'pk': game_id})
def render_to_response(self, context, **response_kwargs):
game_id = self.kwargs['game_id']
game_detail_url = reverse('core:GameDetail', kwargs={'pk': game_id})
return redirect(to=game_detail_url)
My guess currently is that I just don't know how to get form from the template, many examples on here create the form when requested, the tutorial i've been following create the form in get_context_data, then pass it off to the template. So i've been struggling to figure out how to save or validate if the form is correct.
Sorry for all the text, but these pieces are so interconnected I wanted to make sure I included everything that would be useful. Displaying and reading from the db seem to work, if I manually go in and add votes through the admin panel I can read them successfully, when trying to write a new score through the vote button nothing happens, below is what the terminal window outputs.
[12/Dec/2018 20:24:34] "GET /game/85 HTTP/1.1" 200 2081
[12/Dec/2018 20:46:49] "POST /game/85 HTTP/1.1" 302 0
[12/Dec/2018 20:46:49] "GET /game/vote/85/create HTTP/1.1" 302 0
[12/Dec/2018 20:46:49] "GET /game/85 HTTP/1.1" 200 2081
Oh maybe the url patterns might be useful.
app_name = 'core'
urlpatterns = [
path('', views.MainPage.as_view(), name='MainPage'),
path('games', views.GameList.as_view(), name='GameList'),
path('game/<int:pk>', views.GameDetail.as_view(), name='GameDetail'),
path('game/vote/<int:game_id>/create', views.CreateVote.as_view(), name='CreateVote'),
path('game/vote/<int:game_id>/update/<int:pk>', views.UpdateVote.as_view(), name='UpdateVote'),
]
Thanks in advance, i've been beating my head against the wall on this one for a while.
Try adding type="submit" to your button:
<button class="btn btn-primary" type="submit">Vote</button >
and then in your CreateView add a form_valid method:
class CreateVote(LoginRequiredMixin, CreateView):
model = Vote
template_name = 'folder/create_vote.html'
form_class = VoteForm
...
def form_valid(self, form):
vote = form.save(commit=False)
game = Game.objects.get(id=game_id)
vote.game = game
vote.save() # You have to save the vote for it to be added to the db.
return HttpResponseRedirect(reverse('redirect_view'))
This had a painful solution, a simple typo. In my GameDetail's get_context_data I setup data for the template to use, one of those fields was the url to post to
ctx['vote_from_url'] = vote_form_url
In the template when I attempted to reference this I misspelled it
action="{{ vote_form_url }}" >
The frustrating thing for me is that this does not come up with an error, in the template if I put anything it defaults to the url of the parent view. I should have noticed that POST was going to the wrong URL, but I wonder if there is a setting or log that would have told me I was referencing something in the template that doesn't exist. Hope this recap helps someone that get stuck in a similar situation.
maybe a bit late and not exactly the same case but i had the same issue with FIELDSET :
PK(id) had to be included in the form.
Discovered this with adding this in my template:
{% for hidden_fields in formset %}
{{ hidden_fields.errors }}
{% endfor %}
Then, when "SUBMIT", this showed :
id
Ce champ est obligatoire.
id
Ce champ est obligatoire.
id
Ce champ est obligatoire...
(champ obligatoire <=> mandatory field)
After adding the hidden TD, data were well saved :
<tbody>
{% for form in formset %}
<tr>
<td class="hidden">{{ form.id }}</td>
<td>{{ form.ean }}</td>
<td>{{ form.used }}</td>
</tr>
{% endfor %}
</tbody>
Not sure it's the best way of doing but it worked for me
Over the last few days I have been working on building a Django web application for allowing users to make queries on a MLB Statistics database. I have some of the web app working fine, however I tried to implement a search function and ran into problems with the URL mapping. I tried to move on from this and instead work on getting the database to display information based on the link to the player that they click on, but I am running into the same issue with the URL's being dynamic based on the player's player_id. This portion only uses the People model which has player_id as its primary key.
Currently, I have an 'allPlayers.html' that lists every player in the database along with a link sending the player's player_id to the url as so:
allPlayers.html
{% extends "base_template.html" %}
{% block content %}
<h1>MLB Stats All Players</h1>
<p>Currently, there are : {{ num_players }} players listed in the database.</p>
<table style="width:100%">
<tr>
<th>First Name</th>
<th>Last Name</th>
<th></th>
</tr>
{% for player in players %}
<tr>
<td>{{ player.name_first }}</td>
<td>{{ player.name_last }}</td>
<td>More on {{ player.name_first }} {{ player.name_last }}</td>
</tr>
{% endfor %}
</table>
{% endblock %}
And the corresponding view for 'allPlayers.html':
def allplayers(request):
"""View function for allPlayers page of site."""
# Generate counts of people object
num_players = People.objects.count()
players = People.objects.all()
context = {
'num_players': num_players,
'players': players,
}
# Render the HTML template allPlayers.html w/ data in context variable
return render(request, 'allPlayers.html', context=context)
With just the above I have successfully created a page on my web app that lists each player in the database along with a link, and notice that I am trying to send the player_id through <a href='players/{{ player.player_id }}>. Currently the allPlayers portion works fine. However, things go south when I add the following playerInfo.html and corresponding view:
playerInfo.html
{% extends "base_template.html" %}
{% block content %}
{% if results %}
{% for player in results %}
<p>{{ player.name_first }} {{ player.name_last }}</p>
{% endfor %}
{% endif %}
{% endblock %}
And the view:
def player(request, pk=None):
if pk is not None:
print('Hello world')
print('pk :', pk)
#instance = get_object_or_404(People, player_id=pk)
results = People.object.filter(player_id=pk)
context = {
"results": results
}
return render(request, "playerInfo.html", context)
else:
print('Hello')
return render(request, 'playerInfo.html')
My idea was that the link noted earlier containing {{ player.player_id }} would match up with the following url and place the player_id value in for pk, as follows using the <int:pk> syntax instead of regex:
polls/urls.py
urlpatterns = [
path('', views.index, name='index'),
path('allPlayers', views.allplayers, name='allplayers'),
path('allTeams', views.allteams, name='allteams'),
path('search/', views.search, name='search'),
path('player/<int:pk>/', views.player, name='player'),
]
However, once I navigate to my 'allPlayers' page and click on one of the links for the player, say Hank Aaron (who has player_id aaronha01), I get the following Page not found (404) error:
Using the URLconf defined in baseballdb.urls, Django tried these URL patterns, in this order:
polls/ [name='index']
polls/ allPlayers [name='allplayers']
polls/ allTeams [name='allteams']
polls/ search/ [name='search']
polls/ player/<int:pk>/ [name='player']
admin/
The current path, polls/player/aaronha01/, didn't match any of these.
I have been having trouble with this for quite a bit now. If anyone has any advice and can point me in the right direction of how I'm thinking about this incorrectly or has a solution for me that would be seriously greatly appreciated! Thank you.
path('player/<int:pk>/' means only valid int pk would match. If your pk is not int and something like a valid slug - use path('player/<slug:pk>/' instead.
docs: https://docs.djangoproject.com/en/2.1/topics/http/urls/#path-converters
And my suggestion is to use {{ player.get_absolute_url }} or {% url 'player' player.id %} instead of building url manually.
Missing leading slash means "from here", not from website root:
https://webmasters.stackexchange.com/questions/56840/what-is-the-purpose-of-leading-slash-in-html-urls
There is a mismatch between <int:pk> in your path(), which expects an integer, and your player_id, which is a string like 'aaronha01'.
You can either use the pk everywhere, and have urls like /player/17/:
path('player/<int:pk>/', views.player, name='player'),
def player(request, pk):
instance = get_object_or_404(People, pk=pk)
context = {
"instance": instance,
}
return render(request, "playerInfo.html", context)
# Use pk in template when constructing URL
<td>More on {{ player.name_first }} {{ player.name_last }}</td>
Or you can use player_id everywhere, and have urls like /player/aaronha01/.
path('player/<slug:player_id>/', views.player, name='player'),
def player(request, player_id):
instance = get_object_or_404(People, player_id=player_id)
context = {
"instance": instance,
}
return render(request, "playerInfo.html", context)
# Use player_id in template when constructing URL
<td>More on {{ player.name_first }} {{ player.name_last }}</td>
As a next improvement, you can start using the {% url %} tag so that you aren't hardcoding the URLs anymore.
<a href="{% url "polls:player" player.player_id %}">
In the above, I've assumed that you have app_name='polls' in your polls/urls.py, and that you have decided to use player_id instead of pk in your url pattern.
I have an upload dashboard where it displays the users files. The files are represented by a model, and there a view for the dashboard, and a second for the delete action.
Here is the model for the file upload and the related model client:
#python_2_unicode_compatible
class ClientUpload(models.Model):
client = models.ForeignKey(Client)
created_at = models.DateTimeField(auto_now_add=True)
file_upload = models.FileField(upload_to=generate_filename)
def __str__(self):
return self.client.company
class Meta:
verbose_name_plural = _("Client Uploads")
verbose_name = _("Client Upload")
#python_2_unicode_compatible
class Client(models.Model):
user = models.OneToOneField(User)
company = models.CharField(max_length=100)
def __str__(self):
return self.company
class Meta:
verbose_name_plural = _("Clients")
verbose_name = _("Client")
permissions = (
("can_upload", _("Can upload files.")),
("can_access_uploads", _("Can access upload dashboard.")),
("is_client", _("Is a client.")),
)
Here is the url pattern for the delete view:
url(r'^dashboard/delete/(?P<upload_id>\d+)$', views.dashboard_delete, name='dashboard-delete'),
Here is the view for the dashboard and the dashboard delete action:
def dashboard_delete(request, upload_id):
p = get_object_or_404(ClientUpload, pk=upload_id)
p.delete()
return HttpResponseRedirect(reverse('dashboard'))
#login_required(login_url='/dashboard-login/')
def dashboard(request):
current_user = request.user
current_client = request.user.client
files = ClientUpload.objects.filter(client=current_client)
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
dz_files = request.FILES.getlist('file_upload')
for f in dz_files:
new_file = ClientUpload(client=current_client, file_upload=f)
new_file.save()
logger = logging.getLogger(__name__)
logger.info("File uploaded from " + current_client.company)
else:
logger = logging.getLogger(__name__)
logger.warning("Upload Failed")
return HttpResponseRedirect(reverse('dashboard'))
else:
form = UploadFileForm()
data = {'form': form, 'client': current_client, 'files': files}
return render_to_response('dashboard.html', data, context_instance=RequestContext(request))
and finally the section of the template for the file listing where the dashboard-delete view is called from:
<table class="table">
<tr>
<th>{% blocktrans %}Filename{% endblocktrans %}</th>
<th>{% blocktrans %}Size (Bytes){% endblocktrans %}</th>
<th>{% blocktrans %}Upload Time{% endblocktrans %}</th>
<th>{% blocktrans %}Actions{% endblocktrans %}</th>
</tr>
{% for file in files %}
{% with uploaded_file=file.file_upload %}
<tr>
<th>{{ uploaded_file.name|pathend }}</th>
<th>{{ uploaded_file.size }}</th>
<th>{{ file.created_at }}</th>
<th><i class="fa fa-search"></i><i class="fa fa-trash-o"></i></th>
{% endwith %}
{% endfor %}
</tr>
</table>
In actions there is an icon with an anchor to the dashboard-delete named url. I pass in the current files id. And then in the url.py file I pass it in the regex. The view then finds and deletes the file. I use get_object_or_404() and get no 404 but the page just refreshes and nothing is deleted. For some reason when I press the delete icon I get two requests to /dashboard/delete/5 (5 would be the upload_id for that file) rather than just one.
Any help would be hugely appreciated, why are my models not being deleted, the page reloads and that's it. I cannot find what is wrong. I tried using catch redirect with the dj debug toolbar but it doesn't capture the redirect back to dashboard from dashboard-delete view. Which makes no sense, ordinarily it would catch the redirect.
If you need more information or need to see more code let me know and I will post it but you should have what you need to figure it out. I've been stuck here for a week so I could really use some help to finally get his done.
I know the ID's are correct because they are in the Admin panel as the same numbers and when I hover over I see which ID each item is and they line up with the Admin panel's ID's. I also tried doing {% url 'dashboard-delete' upload_id=file.id %} and it didn't work either, I don't think it has to be a kwarg in this case anyway.
I am completely stumpped here. I've done this exact method many times and it has always worked. What am I missing?
EDIT:
After further testing, it seems the view is never even getting called which makes no sense. When I hover over the link I get the correct URL, but the view never gets called. I put a logging line at the top and it never occurs. Why would this be? What would cause it not to be called?
Noticed that it seems the view doesn't even get called at all. I cant even execute a log statement from inside on the first line. Why would this happen? I've used the same delete views before, and I even tried a CBV with DeleteView.
I had to move my /dashboard/delete above /dashboard in urlpatterns, I knew this and had forgotten. Works now. Stupid me.
I'm trying to create a custom placeholder to add an admin-editable section on a website. Django-cms' documentation is really generic about what's to be done to add it.
The placeholder lives in a separate app, called contacts, already added to the settings.py file
Here's my code up to now (skipping imports to be less verbose):
models.py
class ContactsPlaceholder(models.Model):
phone = models.CharField(max_length=100)
email = models.CharField(max_length=100)
address = models.TextField(max_length=700)
# your fields
my_placeholder = PlaceholderField('contacts_contactsplaceholder')
# your methods
def __unicode__(self):
return "Contacts Placeholder"
views.py
def contacts(request):
# Load the the contacts from db
contactsfields = ContactsField.objects.all()
contacts_placeholder = ContactsPlaceholder.objects.all()
context = {"contactsfields" : contactsfields, "contacts_placeholder" : contacts_placeholder}
return render(request, "../templates/contacts.html", context)
def contacts_placeholder_detail(request, id): # is this really useful?
object = get_object_or_404(ContactsPlaceholder, id=id)
return render_to_response('../templates/contacts_placeholder_detail.html', {
'object': object,
}, context_instance=RequestContext(request))
contacts.html
{% extends "base.html" %}
{% load cms_tags %}
{% block content %}
<div>
<h1>Contacts</h1>
{% placeholder "contacts_placeholder" or %}
<p>Placeholder is empty</p>
{% endplaceholder %}
</div>
{% endblock content %}
and finally, admin.py
class ContactsPlaceholderAdmin(PlaceholderAdminMixin, admin.ModelAdmin):
# Editable fields
frontend_editable_fields = ("phone", "email", "address")
# Form fields order and sections
fieldsets = [
(None,{"fields" : ["phone", "email", "address"]})
]
admin.site.register(ContactsPlaceholder, ContactsPlaceholderAdmin)
With this configuration, after having run python manage.py syncdb I do get "Placeholder is empty" in the html response, and of course the placeholder is not editable using the standard frontend editor, which was the desired behaviour.
Going to 127.0.0.1:8000/admin/ i can see the "Contacts Placeholder" table, however when I click it or try to add items I do get the following error:
OperationalError at /us/admin/contacts/contactsplaceholder/
no such column: contacts_contactsplaceholder.phone
If the contacts() view is rendered via an app hook then using {% placeholder "contacts_placeholder" %} in the template won't work.
When using Placeholders in apps connected to the CMS via an AppHook you must use {% static_placeholder "MyPlaceholder" %} instead of the usual {% Placeholder "MyPlaceholder" %}
If you've got an app or a plugin in which you've created a PlaceholderField, then in your template which renders that, you'd need the following tag;
{% render_placeholder instance.placeholderfieldname %}