I've been working on an issue all day and am at my wits end. I have two models with a manytomany relationship (bookmark, and boomark group). I am trying to access the bookmarks accosiated with the bookgroup in my view. When print the context to take a peak I get None returned. I've pasted the code below in a gist...any help would be so greatly appreciated.
models.py
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from itertools import chain
import datetime
import hashlib
from django.db import models
from django.urls import reverse
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django_mysql.models import JSONField, Model
from django.template.loader import render_to_string
from django.core.mail import send_mail
from django.utils import timezone
from django.conf import settings
class Bookmark(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
resource = models.ForeignKey("Resource", on_delete=models.CASCADE, related_name="bookmarks")
bookmark_groups = models.ManyToManyField("BookmarkGroup")
# meta
created_at = models.DateTimeField(auto_now_add=True)
modified_at = models.DateTimeField(auto_now=True)
class Meta:
unique_together = ('user', 'resource',)
ordering = ('resource',)
def __str__(self):
return "{} | {}".format(self.user, self.resource)
class BookmarkGroup(models.Model):
name = models.CharField(max_length=50)
slug = models.SlugField(null=False, unique=True)
bmark = models.ManyToManyField(Bookmark)
def __str__(self):
return self.name
views.py
from __future__ import unicode_literals
import json
from django.shortcuts import render, get_list_or_404
from django.http import JsonResponse
from django.views import View
from django.views.generic import DetailView
from app.serializers import BookmarkGroupSerializer
from app.models import Resource,Bookmark,ResourceShare,PrivateNote,BookmarkGroup
from app.views.resources import get_enriched_resources
class BookmarkGroupView(DetailView):
model = BookmarkGroup
def get_context_data(self, **kwargs):
context = super(BookmarkGroupView, self).get_context_data(**kwargs)
print(context['object'].bmark.resource)
return context
The key here is ManyToMany relationship, but you are trying to access it like a single object.
context['object'].bmark.all()[0].resource
OR
context['object'].bmark.first().resource
UPDATED:
With emptiness check
try:
resourse = context['object'].bmark.all()[0].resource
except:
resourse = None
OR
bmarks = context['object'].bmark.all()
resourse = bmarks[0].resource if bmarks else None
Related
I would like to display values from one table, but filter these values based on a value from another table.
for example: I want to display values from data/models.py that are filtered by the customer_tag in the CustomUser table (accounts/models.py).
These are related tables, but I can't figure out the right syntax to filter this view.
Any ideas? Or is this not possible with my current schema..
data/views.py
from django.views.generic import ListView, DetailView
from django.views.generic.edit import UpdateView, DeleteView, CreateView
from django.urls import reverse_lazy
from .models import Data
from django.contrib.auth.mixins import LoginRequiredMixin
from rest_framework import generics
from .models import Data
from accounts.models import CustomUser
from .serializers import DataSerializer
from .permissions import IsAuthorOrReadOnly
class DataListView(LoginRequiredMixin,ListView):
queryset = Data.objects.all()
context = {
"object_list": queryset
}
template_name = 'data_list.html'
login_url = 'login'
accounts/models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class CustomUser(AbstractUser):
customer_Tag = models.CharField(max_length=50,)
isAdmin = models.BooleanField(default = False,)
notifications = models.BooleanField(default = True,)
deviceSerial= models.CharField(max_length=50,)
machineName= models.CharField(max_length=50,default="ESP1",)
machineDescription = models.CharField(max_length=200,)
class Customer(models.Model):
customerTag= models.CharField(max_length=50,)
customerName = models.CharField(max_length=50,)
mainContact = models.CharField(max_length=100,default='',)
Address = models.CharField(max_length=100,default='',)
city = models.CharField(max_length=100,default='',)
website = models.URLField(max_length=100,default='',)
phone = models.IntegerField(default=0,)
def __str__(self):
return self.customerName
data/models.py
from django.db import models
from django.conf import settings
from django.contrib.auth import get_user_model
class Data(models.Model):
author = models.ForeignKey(get_user_model(),on_delete=models.CASCADE,)
tempData= models.CharField(max_length=50,blank=True,)
humidData= models.CharField(max_length=50,blank=True,)
def __str__(self):
return str(self.author)
It's all in the docs: https://docs.djangoproject.com/en/2.1/topics/db/queries/#lookups-that-span-relationships
Fields of related models are queried using double underscores __ in a filter.
In your case you need to override get_queryset method of your DataListView class to return a filtered queryset:
class DataListView(LoginRequiredMixin,ListView):
...
def get_queryset(self):
return self.queryset.filter(author__customerTag=self.request.user.customerTag)
I think you are looking for the key__field argument of the filter query if I understood you correctly. So in your case it would be something like,
Data.objects.filter(author__customer_tag='tag-you-are-looking-for') # double underscores after author
Hope this answers your question!
I have a view I am calling when a user clicks a button on the site, it pulls JSON data(from the Coinbase API) and converts it to a string and should save the string pulled to the current user's account.
Whenever they click the button it will pull the string, but nothing is saved to the account, which is the issue.
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from ico_login.models import UserAddress
from coinbase.wallet.client import Client
#login_required()
def generate_address_btc(request, *args, **kwargs):
client = Client('api', 'key')
r = client.get_addresses('account_id')
address = r['data'][0]['address']
request.user.address = str(address)
request.user.save()
return HttpResponse(address)
models.py
from django.db import models
from django.contrib.auth.models import User
class UserAddress(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
address = models.CharField(max_length=300, default=' ')
urls.py
from django.contrib import admin
from django.urls import path, include
from ico_details import views
urlpatterns = [
path('create_address/', views.generate_address_btc, name='generate')
]
In your view you write request.user.address = ..., so you add the attribute address to a User object. As far as I read your code, this is not what you want. You would like to put str(address) into the field address of the object UserAddress related to the User object from request.user, right?!
So, here are the suggested edits to do so:
models.py
from django.db import models
from django.contrib.auth.models import User
class UserAddress(models.Model):
# next line changed
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user_address')
address = models.CharField(max_length=300, default=' ')
views.py
from django.shortcuts import render
from django.http import HttpResponse
from django.contrib.auth.decorators import login_required
from ico_login.models import UserAddress
from coinbase.wallet.client import Client
#login_required()
def generate_address_btc(request, *args, **kwargs):
client = Client('api', 'key')
r = client.get_addresses('account_id')
address = r['data'][0]['address']
# next 2 lines changed
request.user.user_address.address = str(address)
request.user.user_address.save()
return HttpResponse(address)
Hope that helped and happy coding!
I have the following views.py:
from django.template import loader
from django.http import HttpResponse
from django.shortcuts import get_object_or_404
from django.contrib.auth.decorators import login_required
from student.models import CustomUser
from student.forms import UserForm
from django.template.context_processors import csrf
from django.shortcuts import render_to_response
from django.contrib.auth.signals import user_logged_in
from .models import UserSession
def user_logged_in_handler(sender,request,CustomUser,**kwargs):
UserSession.objects.get_or_create(
user=CustomUser,
session_id= request.session.session_key
)
user_logged_in.connect(user_logged_in_handler)
def delete_user_sessions(CustomUser):
user_sessions=UserSession.objects.filter(user=CustomUser)
for user_session in user_sessions:
user_session.session.delete()
I have the following models.py:
class UserSession(models.Model):
user= models.ForeignKey(settings.AUTH_USER_MODEL)
session=models.ForeignKey(Session)
Also in models.py I have class CustomUser(AbstractUser). What's wrong in my views.py as the error says when I try to access /admin/
invalid literal for int() with base 10: 'iie27cmjouht24y424g44s5qlm999vcj'
The full models.py is as follows:
from django.utils import timezone
from django.conf import settings
from django.contrib.auth.models import AbstractUser
from django.utils.translation import ugettext_lazy as _
from django.contrib.sessions.models import Session
class CustomUser(AbstractUser):
addr1= models.CharField(max_length=20)
addr2= models.CharField(max_length=20)
city= models.CharField(max_length=20)
state= models.CharField(max_length=20)
country= models.CharField(max_length=20,choices=country_choices)
pincode= models.IntegerField(default=0,blank=True,null=True)
securityq= models.CharField(max_length=20)
securitya= models.CharField(max_length=20)
class userresp(models.Model):
uid=models.ForeignKey(settings.AUTH_USER_MODEL,blank=True,null=True)
resp=models.CharField(max_length=20)
datetime=models.DateTimeField(default=timezone.now)
def __unicode__(self):
return u"{} {}".format(self.uid,self.datetime)
class Meta:
db_table="userresp"
class UserSession(models.Model):
user= models.ForeignKey(settings.AUTH_USER_MODEL)
session=models.ForeignKey(Session)
What can I do here?
he error is sorted...
def user_logged_in_handler(sender,request,user, **kwargs):
UserSession.objects.get_or_create(
user= user,
session_id= request.session.session_key
)
user_logged_in.connect(user_logged_in_handler, sender=CustomUser)
The error is coming from this line in your code session_id= request.session.session_key. Django expects the session id to be an int but the session key being generated is string. Check and make sure that you are asking for the correct data.
I started to code a two-apps django project. ModelA belongs to appone and ModelB belongs to apptwo. My purpose is to create a ModelA instance everytime that the user creates a ModelB instance. And the value of a ModelA CharField (that is ckeditor widgeted) must be the source code of a ModelB admin view. I used a post_data signal to link a function of creation for that. The problem is that i use the id of each instance of ModelB in order to create the good content for each instance of ModelA. When I try to use a string of the url sending the id parameter, the content field has for value the source code of the debug page
(error 500, DoesNotExist at /admin/apptwo/modelb/my_view/ref=76, [76 is an example] ModelB matching query does not exist. Exception location : /home/me/Desktop/env/lib/python3.5/site-packages/django/db/models/query.py in get, line 385)
But when I try to visit the url "http://localhost:8000//admin/apptwo/modelb/my_view/ref=76", or when I hardcode the url, without a str(instance.id), the page exists and everything works perfectly.
I don't understand why.
Could anybody give me some help to solve this problem ?
Thanks in advance,
PS :
The first app has a model.py that contains the following code :
from django.db import models
from django.contrib.auth.models import User
from registre.models import *
class ModelA(models.Model):
content = models.CharField(max_length=255, null=True)
def __str__(self):
return "ModelA : " + str(self.id)
the admin.py of this first app also contains :
from django.contrib import admin
from appone.models import *
from apptwo.models import ModelB
from django.http import HttpResponse
from django.template.response import TemplateResponse
from django.conf.urls import url
from registre import views
from django.db.models.signals import post_save
from django.dispatch import receiver
import datetime
from django.contrib.auth.models import User
from django import forms
from ckeditor.widgets import CKEditorWidget
from django.template.loader import render_to_string
import requests
class ModelAAdminForm(forms.ModelForm):
content = forms.CharField(widget=CKEditorWidget())
class Meta:
model = ModelA
fields = '__all__'
class ModelAAdmin(admin.ModelAdmin):
form = ModelAAdminForm
def create_A(sender, instance, **kwargs):
string = "http://localhost:8000/admin/apptwo/modelb/my_view/ref=" + str(instance.id)
r = requests.get(string)
ModelA.objects.create(contenu=r.text.encode('utf-8'))
post_save.connect(create_A, sender=ModelB)
admin.site.register(ModelA, ModelAAdmin)
the second app (apptwo) has a models.py like this :
from django.db import models
from django.contrib.auth.models import User
class ModelB(models.Model):
owner = models.ForeignKey(User, null=True)
name = models.CharField(max_length=255, null=True)
def __str__(self):
return self.name
and an admin.py that contains :
from django.contrib import admin
from appone.models import *
from apptwo.models import *
import datetime
from django.conf.urls import url, include
from django.template.response import TemplateResponse
class ModelBAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(ModelB, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)
def save_model(self, request, obj, form, change):
obj.owner = request.user
obj.save()
def get_urls(self):
urls = super(ModelBAdmin, self).get_urls()
my_urls = [
url(r'^my_view/ref=(?P<id>\d+)$', self.my_view),
]
return my_urls + urls
def my_view(self, request, id):
context = dict(
self.admin_site.each_context(request),
selector = ModelB.objects.get(id=id),
)
return TemplateResponse(request, "myview.html", context)
admin.site.register(ModelB, ModelBAdmin)
and finally a template myview.html with :
<p>Test {{ selector.name }}</p>
every one, I am working the project (use django 1.8 ) have a ForeignKey, and I have to upload image file through the api,but I just fail to do it,,can any one tell me how to do it,thank you.
within the models.py there is a class Upload(models.Model): it has the ForeignKey thing = models.ForeignKey(ProductsTbl, related_name="uploads") to class ProductsTbl(models.Model):
models.py
class ProductsTbl(models.Model):
......
model_number = models.CharField()
name = models.CharField(max_length=255, blank=True, null=True)
material = models.CharField(max_length=255, blank=True, null=True)
.......
def __unicode__(self):
return self.name
def save(self, *args, **kwargs):
''' On save, update timestamps '''
if not self.id:
self.created = timezone.now()
return super(ProductsTbl, self).save(*args, **kwargs)
def get_image_path(instance, filename):
return '/'.join(['thing_images', instance.thing.slug, filename])
class Upload(models.Model):
thing = models.ForeignKey(ProductsTbl, related_name="uploads")
image = models.ImageField(upload_to=get_image_path, verbose_name='Image')
..........
api/serializers.py
from rest_framework import serializers
from ..models import *
from django.contrib.auth.models import User
from django.contrib.auth import get_user_model
UserModel = get_user_model()
class ProductsTblSerializer(serializers.ModelSerializer):
class Meta:
model = ProductsTbl
fields = ('model_number','name','material',)
class UploadSerializer(serializers.ModelSerializer):
ProductsTbl = serializers.CharField(source='ProductsTbl.id')
class Meta:
model = Upload
fields = ('thing','image')
........
api/urls.py
from django.conf.urls import url, include
from . import views
urlpatterns = [
url(r'^productsTbls/$', views.ProductsTblListView.as_view(), name='productsTbls_list'),
url(r'^productsTbls/(?P<pk>\d+)/$', views.ProductsTblDetailView.as_view(), name='productsTbls_detail'),
url(r'^Upload/(?P<pk>\d+)/$', views.UploadDetailView.as_view(), name='Upload_Detail'),
......
]
api/views.py
from rest_framework import generics
from ..models import *
from .serializers import ProductsTblSerializer,UploadSerializer,UserSerializer
from django.contrib.auth.decorators import login_required
from django.http import Http404, HttpResponse
from django.shortcuts import render, redirect
from rest_framework.renderers import JSONRenderer
from rest_framework.parsers import JSONParser
from django.views.decorators.csrf import csrf_exempt
from django.forms import modelformset_factory
from django.template.defaultfilters import slugify
from rest_framework import permissions
from rest_framework.generics import CreateAPIView
from django.contrib.auth import get_user_model
from rest_framework.permissions import AllowAny
class ProductsTblListView(generics.ListCreateAPIView):
queryset = ProductsTbl.objects.order_by('-created')
serializer_class = ProductsTblSerializer
class ProductsTblDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = ProductsTbl.objects.all()
serializer_class = ProductsTblSerializer
class UploadDetailView(generics.RetrieveUpdateDestroyAPIView):
queryset = Upload.objects.all()
serializer_class = UploadSerializer
......
settings.py
........
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': [
'rest_framework.permissions.AllowAny',
#'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
]
}
.......
when I try to upload image through PUT , I just seeing {"detail":"Not found."}