Name of pattern where an object is stored by UUID - oop

I am programming an application where I want to store Session information by a UUID. For this purpose, I wrote this code:
import uuid
class ObjectStore:
def __init__(self):
self.objects = {}
def add(self, obj):
uuid_value = uuid.uuid4() # UUID4 generates a random UUID
self.objects[uuid_value] = obj
return uuid_value
def retrieve(self, uuid):
return self.objects[uuid]
Is this structure a common pattern? If so, does it have a name?

Related

permission_classes doesn't work . where is problem?

I'm trying to found how Restframework's permission work , so i try write some code that response a simple Json. But the existence or absence of a ā€¨permission_classes does not affect the execution of the code and endpoint will response all request without checking any permission.
here is my code:
class TeacherStatisticPost(generics.RetrieveAPIView):
permission_classes = (ClassOwnerPermission)
queryset = ClassRoom.objects.all()
lookup_field = "id"
lookup_url_kwarg = 'classRoom_id'
def get_klass(self):
class_id = self.kwargs['classRoom_id']
return ClassRoom.objects.get(id=classRoom_id)
def get(self, request, *arg, **kwargs):
klass = self.get_klass()
response ={
'class_room_grade' : klass.grade,
'class_room_name' : klass.name,
}
return JsonResponse(response, safe=False)
and here is my permission.py:
class ClassOwnerPermission(permissions.BasePermission):
def has_perm(self, user, klass):
print("now in class perm") # never print out any thing!
return klass.owner == user
def has_object_permission(self, request, view, obj): # where is come from 'obj' ?
return self.has_perm(request.user, obj)
im try to set permission that just owner of ClassRoom can access to this endpoint.
Firstly, DRF expects permission_classes to be list or tuple. permission_classes at the line permission_classes = (ClassOwnerPermission) is not neither tuple not list. Put comma after the ClassOwnerPermission.
The line permission_classes = (ClassOwnerPermission, ) should work.
Secondly, you do not use get_object method which checks the permissions. Remove def get_klass(self): method and use get_object
Your view should look like following:
class TeacherStatisticPost(generics.RetrieveAPIView):
permission_classes = (ClassOwnerPermission, )
queryset = ClassRoom.objects.all()
lookup_field = "id"
lookup_url_kwarg = 'classRoom_id'
def get(self, request, *arg, **kwargs):
klass = self.get_object()
response ={
'class_room_grade' : klass.grade,
'class_room_name' : klass.name,
}
return JsonResponse(response, safe=False)

How to set permissions for a POST request in ModelViewSet's

How can I write my own permission class for POST requests when using ModelViewSet?
I already tried to write my own permission_classe with no success. Even if my permission class is returning false it is still granting access to the post request
models.py
class Building(models.Model, HitCountMixin):
user = models.ForeignKey(User, on_delete=models.CASCADE) limit_choices_to=Q(country=2921044) | Q(country=798544), on_delete=models.SET_NULL) #<------------ Eltern Element
name = models.CharField(max_length=200, null=True, blank=True)
description = models.TextField(max_length=2000,null=True, blank=True)
facilities = models.TextField(max_length=2000, null=True, blank=True)
...
views.py
class BuildingImageViewSet(viewsets.ModelViewSet):
"""
API endpoint that allows groups to be viewed or edited.
"""
serializer_class = BuildingImageSerializer
permission_classes = (permissions.IsAuthenticated, IsOwner,)
def get_queryset(self):
if self.request.user.is_authenticated:
return BuildingImage.objects.filter(building__user=self.request.user)
return None
permissions.py
class IsOwner(permissions.BasePermission):
def has_object_permission(self, request, view, obj):
print("TEST")
return False
urls.py
router = routers.DefaultRouter()
router.register(r'buildingimages', myrest_views.BuildingImageViewSet, base_name="buildingimage")
If I I try to upload an image it is working, Why?
My IsOwner permission class is evaluated because I can see the print line with "TEST" in the console.
MY SOLUTION:
def has_permission(self, request, view):
if view.action == 'create':
building_url = request.POST.get('building')
building_path = urlparse(building_url).path
building_id = resolve(building_path).kwargs['pk']
building = Building.objects.get(id=building_id)
return building.user == request.user
return True
Pass list of classes, you used has_object_permission(), You need to write code inside has_permission() method.
permission_classes = [<class 'rest_framework.permissions.AllowAny'>]
you have to pass class that derive BasePermission class
permission.py
from rest_framework import permissions
class IsOwner(permissions.BasePermission):
def has_permission(self, request, view):
if <CONDITION>:
return True
else:
return False

Custom ConnectionField in graphene

I'm not understanding how to use custom fields in a ConnectionField in graphene. I have something like:
class ShipConnection(Connection):
extra = String()
class Meta:
node = Ship
SHIPS = ['Tug boat', 'Row boat', 'Canoe']
class Query(AbstractType):
ships = relay.ConnectionField(ShipConnection)
def resolve_ships(self, args, context, info):
return ShipConnection(
extra='Some extra text',
edges=???
)
Normally, you'd say:
def resolve_ships(self, args, context, info):
return SHIPS
but how do you return something in extra and return a list?
The answer turns out to be to use an undocumented class method of graphene's ConnectionField class, called resolve_connection. The following works:
def resolve_ships(self, args, context, info):
field = relay.ConnectionField.resolve_connection(
ShipConnection,
args,
SHIPS
)
field.extra = 'Whatever'
return field
The proper way to do this is exactly explained here.
class Ship(graphene.ObjectType):
ship_type = String()
def resolve_ship_type(self, info):
return self.ship_type
class Meta:
interfaces = (Node,)
class ShipConnection(Connection):
total_count = Int() # i've found count on connections very useful!
def resolve_total_count(self, info):
return get_count_of_all_ships()
class Meta:
node = Ship
class Edge:
other = String()
def resolve_other(self, info):
return "This is other: " + self.node.other
class Query(graphene.ObjectType):
ships = relay.ConnectionField(ShipConnection)
def resolve_ships(self, info):
return get_list_of_ships_from_database_or_something_idk_its_your_implmentation()
schema = graphene.Schema(query=Query)
I don't know if this is recommended, but the resolve_total_count method can also be implemented as:
def resolve_total_count(self, info):
return len(self.iterable)
I don't know if the iterable property is documented anywhere, but I was able to find it while investigating the Connection class

ApiKey authentication in tastypie with mongoengine

Has anybody had success implementing ApiKey for User from mongoengine.django.auth for use with tastypie ApiKeyAuthentication?
I'm aware of the previous posts on the matter, but they address ORM only, while i'm trying to set it up for mongoengine. Also, it seems that tastypie's own ApiKey class heavily relies on relational structure (using related field api_key of User)
thanks in advance!
following this thread https://github.com/mitar/django-tastypie-mongoengine/issues/25 i've created MongoUser class with api_key field
# models.py (or documents.py)
from mongoengine.django.auth import User
class MongoUser(User):
"""
Subclass of mongoengine.django.auth.User with email as username
and API key for authentication.
"""
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['password']
api_key = StringField(max_length=256, default='')
api_key_created = DateTimeField(help_text=_(u'Created'))
def save(self, *args, **kwargs):
if not self.api_key:
self.set_api_key()
return super(MongoUser, self).save(*args, **kwargs)
def set_api_key(self):
self.api_key = self.generate_key()
self.api_key_created = datetime.now()
def generate_key(self):
new_uuid = uuid.uuid4()
return hmac.new(str(new_uuid), digestmod=sha1).hexdigest()
added a signal (the usual):
# resources.py
from mongoengine import signals
from myapp import models
signals.post_save.connect(create_api_key, sender=models.MongoUser)
and then subclassed tastypie.ApiKeyAuthentication with the following:
# resources.py
class CustomApiKeyAuthentication(ApiKeyAuthentication):
"""
Authenticates everyone if the request is GET otherwise performs
ApiKeyAuthentication.
"""
def is_mongouser_authenticated(self, request):
"""
Custom solution for MongoUser ApiKey authentication.
ApiKey here is not a class (as it is realized in ORM approach),
but a field MongoUser class.
"""
username, api_key = super(CustomApiKeyAuthentication,
self).extract_credentials(request)
try:
models.MongoUser.objects.get(username=username, api_key=api_key)
except models.MongoUser.DoesNotExist:
return False
return True
def is_authenticated(self, request, **kwargs):
"""
Custom solution for `is_authenticated` function: MongoUsers has got
authenticated through custom api_key check.
"""
if request.method == 'GET':
return True
try:
is_authenticated = super(CustomApiKeyAuthentication,
self).is_authenticated(request, **kwargs)
except TypeError as e:
if "MongoUser" in str(e):
is_authenticated = self.is_mongouser_authenticated(request)
else:
is_authenticated = False
return is_authenticated

How do I print the actual contents of this list

The code is short and simple:
class Contact:
all_contacts = []
def __init__(self, name, email):
self.name = name
self.email = email
Contact.all_contacts.append(self)
c1 = Contact("Paul", "something#hotmail.com")
c2 = Contact("Darren", "another_thing#hotmail.com")
c3 = Contact("Jennie", "different#hotmail.com")
for i in Contact.all_contacts:
print(i)
Clearly all I want to do is print the 'all_contacts' list with the info I have added, but what I get is:
<__main__.Contact object at 0x2ccf70>
<__main__.Contact object at 0x2ccf90>
<__main__.Contact object at 0x2ccfd0>
What am I doing wrong?
Add the following to your Contact class:
class Contact:
...
def __str__(self):
return '%s <%s>' % (self.name, self.email)
This will tell Python how to render your object in a human-readable string representation.
Reference information for str
The __repr__ and __str__ methods for Contact aren't defined, so you get this default string representation instead.
def __str__(self):
return '<Contact %s, %s>' % (self.name, self.email)
Separate the container from the items stored in the container.
Add a __str__() method to Contact.
class Contact:
def __init__(self, name, email):
self.name = name
self.email = email
def __str__(self):
return "{} <{}>".format(self.name, self.email)
class ContactList(list):
def add_contact(self, *args):
self.append(Contact(*args))
c = ContactList()
c.add_contact("Paul", "something#hotmail.com")
c.add_contact("Darren", "another_thing#hotmail.com")
c.add_contact("Jennie", "different#hotmail.com")
for i in c:
print(i)