mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-11-04 09:57:55 +03:00 
			
		
		
		
	* Update relations.py
Currently if you define the slug field as a nested relationship in a `SlugRelatedField` while many=False, it will cause an attribute error. For example:
For this code:
```
class SomeSerializer(serializers.ModelSerializer):
    some_field= serializers.SlugRelatedField(queryset=SomeClass.objects.all(), slug_field="foo__bar")
```
The POST request (or save operation) should work just fine, but if you use GET, then it will fail with Attribute error:
> AttributeError: 'SomeClass' object has no attribute 'foo__bar'
Thus I am handling nested relation here. Reference: https://stackoverflow.com/questions/75878103/drf-attributeerror-when-trying-to-creating-a-instance-with-slugrelatedfield-and/75882424#75882424
* Fixed test cases
* code comment changes related to slugrelatedfield
* changes based on pre-commit and removed comma which was added accidentally
* fixed primary keys of the mock object
* added more test cases based on review
---------
Co-authored-by: Arnab Shil <arnab.shil@thermofisher.com>
		
	
			
		
			
				
	
	
		
			60 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			60 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from operator import attrgetter
 | 
						|
 | 
						|
from django.core.exceptions import ObjectDoesNotExist
 | 
						|
from django.urls import NoReverseMatch
 | 
						|
 | 
						|
 | 
						|
class MockObject:
 | 
						|
    def __init__(self, **kwargs):
 | 
						|
        self._kwargs = kwargs
 | 
						|
        for key, val in kwargs.items():
 | 
						|
            setattr(self, key, val)
 | 
						|
 | 
						|
    def __str__(self):
 | 
						|
        kwargs_str = ', '.join([
 | 
						|
            '%s=%s' % (key, value)
 | 
						|
            for key, value in sorted(self._kwargs.items())
 | 
						|
        ])
 | 
						|
        return '<MockObject %s>' % kwargs_str
 | 
						|
 | 
						|
 | 
						|
class MockQueryset:
 | 
						|
    def __init__(self, iterable):
 | 
						|
        self.items = iterable
 | 
						|
 | 
						|
    def __getitem__(self, val):
 | 
						|
        return self.items[val]
 | 
						|
 | 
						|
    def get(self, **lookup):
 | 
						|
        for item in self.items:
 | 
						|
            if all([
 | 
						|
                attrgetter(key.replace('__', '.'))(item) == value
 | 
						|
                for key, value in lookup.items()
 | 
						|
            ]):
 | 
						|
                return item
 | 
						|
        raise ObjectDoesNotExist()
 | 
						|
 | 
						|
 | 
						|
class BadType:
 | 
						|
    """
 | 
						|
    When used as a lookup with a `MockQueryset`, these objects
 | 
						|
    will raise a `TypeError`, as occurs in Django when making
 | 
						|
    queryset lookups with an incorrect type for the lookup value.
 | 
						|
    """
 | 
						|
 | 
						|
    def __eq__(self):
 | 
						|
        raise TypeError()
 | 
						|
 | 
						|
 | 
						|
def mock_reverse(view_name, args=None, kwargs=None, request=None, format=None):
 | 
						|
    args = args or []
 | 
						|
    kwargs = kwargs or {}
 | 
						|
    value = (args + list(kwargs.values()) + ['-'])[0]
 | 
						|
    prefix = 'http://example.org' if request else ''
 | 
						|
    suffix = ('.' + format) if (format is not None) else ''
 | 
						|
    return '%s/%s/%s%s/' % (prefix, view_name, value, suffix)
 | 
						|
 | 
						|
 | 
						|
def fail_reverse(view_name, args=None, kwargs=None, request=None, format=None):
 | 
						|
    raise NoReverseMatch()
 |