nonrel(Mongodb) with tastypie.I have created one resource class which return selected auth_user from the database.Because of some reasons I did change _id field type from ObjectId to Int64.I used raw_query() for accessing desired auth_user but it doesn't seems to work.Can anyone suggest me what should I do to make raw_query() work for UserModel.
Here is my tastypie resource:
class UserResource(ModelResource):
class Meta:
queryset=User.objects.raw_query({'_id':5})
resource_name="user"
fields=["username","first_name","last_name"]
include_resource_uri=False
allowed_methods=["get"]
output:
'UserManager' object has no attribute 'raw_query'
I myself workaround to this problem and for the sake of others help I am answering my own question.Hope this will help someone.
This solution is to create a proxy model.By declaring proxy models we can do opertions on parent model and even can modify manager.
proxy model:
class UserClass(User):
objects = MongoDBManager()
class Meta:
proxy=True
Resource:
class UserResource(ModelResource):
class Meta:
queryset=UserClass.objects.raw_query({'_id':5})
resource_name="user"
fields=["username","first_name","last_name"]
include_resource_uri=False
allowed_methods=["get"]
This is not related to Tastypie at all. Are you sure you need a raw query, or is the above just an example?
By looking at the docs you should be able to do the following:
from django_mongodb_engine.contrib import MongoDBManager
class User(models.Model):
mongo_manager = MongoDBManager()
Then you should be able to use it as you do above, i.e:
queryset=User.mongo_manager.raw_query({'_id':5})
Related
I would like to allow the creation of a comment only to those models that are sub-classing a specific mixin.
For example, a Post model will have a reverse GenericRelation relation to a Comments model. The comments model is using a custom content types mechanism implemented on top of django's due to the fact that the project uses sharding between multiple databases. The reverse relationship from Post model to Comments is needed to be able to delete Comments when a Post is also deleted.
Putting a simple coding example of what I would like to achieve:
class Post(models.Model, HasCommentsMixin):
some_fields = ....
class HasCommentsMixin(models.Model):
has_comments = GenericRelation('comments.Comment')
class Meta:
abstract = True
What I would like would me a way to say inside a permission check of a Model: if class is subclass of HasCommentsMixin, allow the creation of a comment. So for the Post model, comments can be created. But if it's not a subclass the Mixin, comments should not be allowed.
I hope I have provided a description that makes sense. I cannot share real code due to product license and protection.
Thank you.
To achieve this, you can use the isinstance() function in combination with the issubclass() function in the permission check to check if the model is a subclass of the HasCommentsMixin.
class IsCommentAllowed(permissions.BasePermission):
def has_permission(self, request, view):
model = view.get_queryset().model
if isinstance(model, HasCommentsMixin) or issubclass(model, HasCommentsMixin):
return True
return False
I'm using Python 3.6+PostgreSQL 10+latest Django and DjangoRestFRamework. I have the following models, in which several models inherit from a class which is the ForeignKey (One-to-Many) of another class.
class Voteable(models.Model):
Voteable_id = models.BigAutoField(primary_key=True);
class base(Voteable):
class Meta:
abstract = False
class traslated_info(models.Model):
info_about=models.ForeignKey(base)
info_body=models.TextField()
info_language=models.CharField(max_length=2)
class A(base):
A_id=models.BigAutoField(primary_key=True)
A_field=models.TextField()
class B(base):
B_id=models.BigAutoField(primary_key=True)
B_field=models.TextField()
B_belongs_to=models.ForeignKey(A)
class C(base):
C_id=models.BigAutoField(primary_key=True)
C_field=models.TextField()
C_belongs_to=models.ForeignKey(A)
C_belongs_to=models.ForeignKey(B)
Whenever I try saving an object A (via curl), django says that base_ptr is required. I don't know how to model this situation. The end user is not expected to create item base and then item A, B or C. I tried class base as abstract, but an abstract class can't be ForeignKey. I want to automatically create a base class whenever a class A is created.
I think I have two options: A) Remove the ForeignKey and store the language-specific info fields as HStoreField. This makes the code somewhate dependent on Postgree. B) Create some sort of routine that automatically creates parent base item whenever a child A item is created (preserving the one to one relationship).
What do you recommend? Is there some django easy option I'm missing to make option B? I have not found this. Thank you.
Having an autofield as primary_key in the models A, B or C causes this error, as creating a child model doesn't cascade-create parents.
I found two workarounds:
Change autofield option primary_key to false and add
SILENCED_SYSTEM_CHECKS=['fields.E100']
Overriding Viewset create method:
#transaction.atomic
def create(self,request,*args,**kwargs):
request.data['base_ptr'] = base.objects.create(user=request.user,created_date=datetime.utcnow()).pk
return super(viewsets.ModelViewSet,self).create(request,*args,**kwargs)
I will stick with the second, I'm quite sure more issues will arise.
Make your serializer as below, you dont need to create base classes explicitly, it will be created automatically.
class ASerializer(serializers.ModelSerializer):
class Meta:
model = A
read_only_fields = ('base_ptr',)
fields = '__all__'
In Django Rest Framework, what's the appropriate way to write a hyperlinked serializer for a model that has a property that points to a reverse related object or None?
class AModel(models.Model):
a_name = models.CharField()
#property
def current_another_model(self):
# Just an example, could be whatever code that returns an instance
# of ``AnotherModel`` that is related to this instance of ``AModel``
try:
return self.another_model_set.objects.get(blah=7)
except AnotherModel.DoesNotExist:
return
class AnotherModel(models.Model):
blah = models.IntegerField()
our_model = models.ForeignKey(AModel)
How do we write a serializer for AModel that contains the url (or null, of course) for the property current_another_model?
I've tried this (I have a working AnotherModel serializer and view):
class AModelSerializer(serializers.HyperlinkedModelSerializer):
current_another_model = serializers.HyperlinkedRelatedField(read_only=True, view_name='another-model-detail', allow_null=True)
That gets me this error:
django.core.exceptions.ImproperlyConfigured: Could not resolve URL for hyperlinked relationship using view name "another-model-detail". You may have failed to include the related model in your API, or incorrectly configured the `lookup_field` attribute on this field.
Define AnotherModel serializer and define that dependency within AModelSerializer, also add class Meta in your AModelSerializer.
class AModelSerializer(serializers.ModelSerializer):
current_another_model = AnotherModelSerializer(allow_null=True, required=False)
class Meta:
model = AModel
fields = ('current_another_model',)
That code should do the trick for you.
Another way is stick to the official documentation while defining related serializers.
Update: Found quite similar question Django Rest Framework - Could not resolve URL for hyperlinked relationship using view name "user-detail"
which is solved.
I have the following model:
from model_utils.models import TimeStampedModel
class MyModel(TimeStampedModel):
....
name = models.CharField(max_length=100)
....
This model is based on Django Utils (https://django-model-utils.readthedocs.org/en/latest/models.html#timestampedmodel) which adds created and modified fields to my model.
What I need know is way to add a db_index to the modified field of my model. But I can't modify the TimeStampedModel file because it is part of an external dependency.
Do you know any easy solution for this kind of issue?
Thank you.
Yes you can using model Meta.
if you don't need to inherit meta from the TimeStampedModel just use this:
class Meta:
...
otherwise you need to explicitly tell django to look into the parent's meta first like this:
class Meta(TimeStampedModel.Meta):
this might be a hackish solution but maybe you can try using index_together to make django create an index for your model:
like this:
class Meta(TimeStampedModel.Meta):
index_together = [
["modified",],
]
try it out and tell me if it worked
EDIT:
Another solution coming from: How to override the default value of a Model Field from an Abstract Base Class:
try adding this to your MyModel class
MyModel._meta.get_field('modified').db_index = True
I've seen test codes where custom resources are further subclassed.
But it was for the test sake, not for any real use.
Why would anyone want to subclass a resource for obvious reason(but apparently not to me)?
An example would suffice.
I just ran into a situation where I need to subclass a resource.
I have a django model that has several subclasses like so (I've simplified it a lot):
class Information(models.Model):
name = models.CharField)
class Question(Information):
question = models.CharField)
class Link(Information):
url = models.CharField()
I want an API for accessing all of the Information objects, but still want to be able to access all the subclass specific attributes for each subclass. In this case I'd want to have 3 resources:
class InformationResource(ModelResource):
class Meta:
queryset = Information.objects.all()
def dehydrate(self, bundle):
'''Add some extra meta data here'''
class QuestionResource(InformationResource):
class Meta:
queryset = Question.objects.all()
class LinkResource(InformationResource):
class Meta:
queryset = Link.objects.all()
This way I have an api for returning all Information objects (as well as the attributes that are common to all of them), but if I need to access subclass specific attributes I can access them through their subclass resource APIs. Furthermore, these subclassed Resources will have access to all of the methods defined for their superclass. For instance, they can override the superclass' dehydrate method to add more fields.