Skip to content

Commit

Permalink
Merge pull request #27 from ProdByGodfather/26-update-queryset-and-ad…
Browse files Browse the repository at this point in the history
…d-some-fields

update queryset and add contains for searching in `v5.0.2`
  • Loading branch information
ProdByGodfather authored Dec 30, 2024
2 parents ebf5065 + 114191a commit 988fd04
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 28 deletions.
56 changes: 29 additions & 27 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,25 +142,26 @@ To delete a record from the database, use the `delete()` method:
```python
Post.delete(1) # Delete the post with ID 1
```
### Converting to Dictionary and Counting Records
After performing operations on the model, you can convert records to dictionaries using the `to_dict()` method and count the number of records using the `count()` method.
## Converting to Dictionary, Counting Records, and Other Query Methods

#### `to_dict` Method
The `to_dict()` method converts a model instance into a dictionary, making it easier to manipulate and serialize the data.
This section covers how to convert records to dictionaries, count records, and use various query methods like `first()`, `last()`, `exists()`, `order_by()`, `paginate()`, and `contains()`. These methods are essential for data manipulation, debugging, and optimizing query performance.

**Example:**
### `to_dict()` Method
The `to_dict()` method converts a model instance (or a collection of instances) into a dictionary, which is particularly useful for data manipulation and serialization. It makes it easier to work with the data in Python or send it over an API.

#### Example:
```python
# Retrieve a post by ID
post = Post.get(id=1)
# Retrieve all posts
posts = Post.all()

# Convert the post to a dictionary
post_dict = post.all().to_dict()
print(post_dict)
# Output: [{'id': 1, 'title': 'Godfather', 'create_time': '2024-01-01 12:00:00', ...}]
# Convert the collection of posts to a list of dictionaries
posts_dict = posts.to_dict()
print(posts_dict)
# Output: [{'id': 1, 'title': 'Godfather', 'create_time': '2024-01-01 12:00:00', ...}, {...}]
```

#### `count` Method
The `count()` method allows you to get the number of records in a model's table.
The `count()` method returns the number of records that match the query. It’s an efficient way to find the size of a dataset without retrieving the actual data.

**Example:**
```python
Expand All @@ -169,11 +170,21 @@ num_posts = Post.count()
print(num_posts) # Output: 10 (if there are 10 posts in the database)
```

#### `first()`, `last()`, `exists()`, `order_by()`, and `paginate()`
- `first():` Returns the first result or None if no results are present.
- `last():` Returns the last result or None if no results are present.
- `exists():` Checks if any records exist in the `QuerySet`.
- `paginate():` Handles pagination of results, allowing you to retrieve subsets of data based on page and page size.
The `count()` method can also be used after applying filters to count specific records:
```python
# Count the number of posts with a specific title
num_posts_with_title = Post.filter(title='Godfather').count()
print(num_posts_with_title) # Output: 3 (if there are 3 posts with the title 'Godfather')
```



#### `first()`, `last()`, `exists()`, `order_by()`, `paginate()` and `contains()`
- **`first()`**: Returns the first result or `None` if no results are present.
- **`last()`**: Returns the last result or `None` if no results are present.
- **`exists()`**: Checks if any records exist in the `QuerySet`.
- **`paginate()`**: Handles pagination of results, allowing you to retrieve subsets of data based on page and page size.
- **`contains()`**: Performs a case-insensitive search to check if a field contains a specific substring.

**Example:**
```python
Expand All @@ -190,20 +201,11 @@ last_post = Post.all().last()
paginated_posts = Post.all().paginate(1, 5) # Page 1, 5 results per page

# Using multiple querysets in one query
posts = Post.filter(title='Godfather').order_by('create_time').paginate(1, 4).to_dict()
posts = Post.all().contains(title='god').order_by('create_time').paginate(1, 4).to_dict()
```

These methods are particularly useful for data manipulation and debugging, as they provide a simple way to view and interact with your database records.

## Version 4.2.3

- `first():` Added to return the first result in a `QuerySet`.
- `last():` Added to return the last result in a `QuerySet`.
- `exists():` Added to check if any records exist.
- `paginate():` Added to handle pagination for large result sets.


**Important for Developers:** When adding new fields to models, they will default to `NULL`. It’s recommended to recreate the database schema after development is complete to ensure fields have appropriate constraints and default values.

## Contributing

Expand Down
Empty file added abarorm/fields/__init__.py
Empty file.
36 changes: 36 additions & 0 deletions abarorm/psql.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,42 @@ def paginate(self, page: int, page_size: int):
# Return a new QuerySet with paginated results
return self.__class__(paginated_results, self.total_count, page, page_size)

def contains(self, field: str, value) -> 'QuerySet':
"""
Performs a case-insensitive 'contains' search for the given field and value.
Can handle various data types such as strings, numbers, and datetime.
:param field: The field name (e.g. 'title').
:param value: The value to search for (e.g. substring for strings or a number).
:return: A new QuerySet with the filtered results.
"""
filtered_results = []

for obj in self.results:
field_value = getattr(obj, field, None)

# If the field's value is a string
if isinstance(field_value, str):
# Perform a case-insensitive substring search
if value.lower() in field_value.lower():
filtered_results.append(obj)
# If the field's value is a number (int, float)
elif isinstance(field_value, (int, float)):
# Check if the number contains the value as a substring (as string)
if str(value) in str(field_value):
filtered_results.append(obj)
# If the field's value is a datetime or date
elif isinstance(field_value, (datetime, date)):
# Check if the value is a substring of the date (formatted as string)
if str(value) in field_value.strftime('%Y-%m-%d'):
filtered_results.append(obj)
# For other field types, apply an appropriate check (e.g., exact match)
elif field_value == value:
filtered_results.append(obj)

return self.__class__(filtered_results, len(filtered_results), self.page, self.page_size)



def __repr__(self):
field_values = {attr: getattr(self, attr) for attr in self.__class__.__dict__ if isinstance(self.__class__.__dict__[attr], Field)}
Expand Down
35 changes: 35 additions & 0 deletions abarorm/sqlite.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,41 @@ def paginate(self, page: int, page_size: int):
paginated_results = self.results[offset:offset + page_size]
# Return a new QuerySet with paginated results
return self.__class__(paginated_results, self.total_count, page, page_size)

def contains(self, field: str, value) -> 'QuerySet':
"""
Performs a case-insensitive 'contains' search for the given field and value.
Can handle various data types such as strings, numbers, and datetime.
:param field: The field name (e.g. 'title').
:param value: The value to search for (e.g. substring for strings or a number).
:return: A new QuerySet with the filtered results.
"""
filtered_results = []

for obj in self.results:
field_value = getattr(obj, field, None)

# If the field's value is a string
if isinstance(field_value, str):
# Perform a case-insensitive substring search
if value.lower() in field_value.lower():
filtered_results.append(obj)
# If the field's value is a number (int, float)
elif isinstance(field_value, (int, float)):
# Check if the number contains the value as a substring (as string)
if str(value) in str(field_value):
filtered_results.append(obj)
# If the field's value is a datetime or date
elif isinstance(field_value, (datetime, date)):
# Check if the value is a substring of the date (formatted as string)
if str(value) in field_value.strftime('%Y-%m-%d'):
filtered_results.append(obj)
# For other field types, apply an appropriate check (e.g., exact match)
elif field_value == value:
filtered_results.append(obj)

return self.__class__(filtered_results, len(filtered_results), self.page, self.page_size)



Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

setup(
name='abarorm',
version='5.0.0',
version='5.0.2',
description='abarorm is a lightweight and easy-to-use Object-Relational Mapping (ORM) library for SQLite and PostgreSQL databases in Python. It aims to provide a simple and intuitive interface for managing database models and interactions.',
long_description=open('README.md').read(),
long_description_content_type='text/markdown',
Expand Down

0 comments on commit 988fd04

Please sign in to comment.